mybatis之映射文件

增删改查

  1. 数据库中需要定义一个表,java定义一个model。

  2. 定义对应接口增删改查

@Mapper
public interface UserMapper {

    List<User> getUserById(int id);

    boolean addUser(User user);

    boolean delUser(int id);

    boolean updateName(User user);
}
  1. 定义映射文件User.xml
    每个mapper标签中namespace属性代表这个xml文件映射的接口。
    每个子标签中有2个属性:

    • id:唯一标识,对应接口中的某个方法。
    • resultType:对应model的全类名。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<mapper namespace="mapper.UserMapper" >
    <select id="getUserById" resultType="model.User">
        select * from user where user_id = #{id};
    </select>
    <insert id="addUser" parameterType="model.User">
        insert into user(name,password) values (#{name},#{password});
    </insert>
    <delete id="delUser">
        delete from user WHERE user_id=#{id};
    </delete>
    <update id="updateName">
        update user SET name=#{name} where user_id=#{userId};
    </update>
</mapper>
  1. 编写测试类进行测试
public class UserMapperTest {

    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void before(){
        try{
            String resource = "generatorConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Test
    public void selectTest() {
        SqlSession openSession=sqlSessionFactory.openSession();
        UserMapper userMapper=openSession.getMapper(UserMapper.class);
        List<User> user=userMapper.getUserById(2);
        System.out.println(user);
        assertTrue(user.size()!=0);
    }

    @Test
    public void addTest() {
        SqlSession openSession=sqlSessionFactory.openSession();
        UserMapper userMapper=openSession.getMapper(UserMapper.class);
        boolean result=userMapper.addUser(new User("小明","123123"));
        openSession.commit();
        assertTrue(result);
    }

    @Test
    public void delTest() {
        SqlSession openSession=sqlSessionFactory.openSession();
        UserMapper userMapper=openSession.getMapper(UserMapper.class);
        boolean result=userMapper.delUser(2);
        openSession.commit();
        assertTrue(result);
    }

    @Test
    public void updateTest() {
        SqlSession openSession=sqlSessionFactory.openSession();
        UserMapper userMapper=openSession.getMapper(UserMapper.class);
        boolean result=userMapper.updateName(new User(3,"123123"));
        openSession.commit();
        assertTrue(result);
    }
}

注意:

  • SqlSession openSession=sqlSessionFactory.openSession();这句话需要openSession.commit();来进行手动提交。
  • 如果SqlSession openSession=sqlSessionFactory.openSession(true);就可以自动提交。
  • 假如想获取insert自增id,那么需要在insert标签中添加2个属性,useGeneratedKey="true"和keyProperty=“id”。这样就可以获取到插入用户自增id了
User user=new User("小明","123123")
boolean result=userMapper.addUser(user);
System.out.printlin(user.getId())

此时打印出的结果就是user的id。

mybatis参数处理

单参数与多参数处理

  • 单个参数随便处理
    举例:
public class UserMapper {
	List<User> getUserById(int id);
}
<select id="getUserById" resultType="model.User">
   select * from user where user_id = #{asasaid};
</select>

这里#{}中不管写什么都是可以识别的。

  • 多个参数会报异常
public class UserMapper {
	List<User> getUserById(int id,String name);
}
<select id="getUserById" resultType="model.User">
   select * from user where user_id = #{id} and name = #{name}
</select>

这里就会报异常。

那么怎么解决呢,只要假如@Param()注解就ok了。

public class UserMapper {
	List<User> getUser(@Param("id")int id,
						@Param("name")String name);
}
  • 最推荐的方法就是传入业务对象也就是model
public class UserMapper {
	List<User> getUser(User user);
}

user中写好id值和name的值。

  • 如果没有对应的model也可以使用map取值。
public class UserMapper {
	List<User> getUser(Map<String,Object> map );
}
public void updateTest() {
        SqlSession openSession=sqlSessionFactory.openSession();
        UserMapper userMapper=openSession.getMapper(UserMapper.class);
        Map<String,Object> map = new HashMap<>()
        map.put("id",1)
        map.put("name","tom")
        boolean result=userMapper.getUser(map);
        openSession.commit();
        assertTrue(result);
    }

#{}与${}的区别

什么是预编译:预编译就是将sql变成一个函数,函数的变量用占位符表示,后面注入的参数系统就会默认它仅仅是一个参数,而不会认为是一个sql语句,不会再次编译,这样就可以防止sql注入。

  • #{}:会将sql语句预编译执行后将#{}中的变量传入语句中从而防止sql注入。
  • ${}:会将sql语句字符串拼接,会导致sql注入问题。

一般情况下使用#{},在原生jdbc不支持占位符情况下用${},比如表名的拼接就需要使用${}。

#{}的一些规则

  • javaType:指定传入的java类型
  • jdbcType:指定存入数据库的类型
  • mode(存储过程)
  • resultMap
  • typeHandler
  • jdbcTypeName
  • espression

比如#{email,javaType=String,jdbcType=varchar(30)}

查询结果集处理

想要返回结果是Map类型

接口Java代码如下;

@MapKey("id")
Map<Integer,User> getUser(int id);

@MapKey指定了Map的键对应的是表中的哪个字段。

resultMap自定义javaBean

<map resource="mapper.UserMapper">
	<resultMap type="model.User" id="user">
		<id column="id" property="id"/>
		<result colume="name" property="name"/>
	</resultMap>
	<select id="getUser" resultMap="user">
		select * from user
	</select>
</map>

id标签指的是主键,result标签指的是普通列。
column代表表中列名,property代表javaBean中的对应命名。

多表联查结果集

比如这时候User中存在Department类,如何查询呢

public class User {
    private int userId;
    private String name;
    private String password;
    private Department department;
}

public class Department {
    private int depId;
    private String depName;
}

方法1

<map resource="mapper.UserMapper">
	<!--方法1-->
	<resultMap type="model.User" id="user">
		<id column="user_id" property="userId"/>
		<result colume="name" property="name"/>
		<result colume="password" property="password"/>
		<result colume="dep_id" property="department.depId"/>
		<result colume="dep_name " property="department.depName"/>
	</resultMap>
	<select id="getUser" resultMap="user">
		select user_id,name,password,dep_id,dep_name from user natrual join department.
	</select>
</map>

方法2:

<map resource="mapper.UserMapper">
	<!--方法2-->
	<resultMap type="model.User" id="user">
		<id column="user_id" property="userId"/>
		<result colume="name" property="name"/>
		<result colume="password" property="password"/>
		<association property="department" javaType="model.Department">
			<id colume="dep_id" property="depId"/>
			<result colume="dep_name " property="depName"/>
		</association>
	</resultMap>
	
	<select id="getUser" resultMap="user">
		select user_id,name,password,dep_id,dep_name from user natrual join department.
	</select>
</map>

方法3:分布查询

此时DeptMapper中就需要getDeptById(int id)接口。

    <!--使用association分布查询-->
    <!--1.根据员工id查询员工信息
        2.根据员工信息中的did值去查询部门信息
        3.部门设置到员工中-->
    <resultMap id="MyEmpByStep" type="com.yuehailin.entity.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <!--association定义关联对象的封装规则-->
        <!--property定义关联对象的javaBean名称-->
        <!--getDeptById定义对应的方法-->
        <!--column定义传入的参数-->
        <association property="dept"
                     select="com.yuehailin.dao.DepartmentMapper.getDeptById"
        column="d_id">
 
        </association>
    </resultMap>
    <!--    public  Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
    SELECT  *  FROM  tbl_employee WHERE  id=#{id}
 
</select>

column属性可以使用{key=value,key2=value}来应对多个属性的值。

延迟加载

在分布查询时,如果只是用到user中的熟悉,如果同时加载department的话会增加内存,只有在用到的时候再加载就叫延迟加载。
Mybatis配置文件中通过两个属性lazyLoadingEnabled和aggressiveLazyLoading来控制延迟加载和按需加载。
在generatorConfig.xml中添加

<settings>
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="true"/>
</settings>

collection嵌套结果集(一对多)

假如有以下场景

public class Type {

    private int typeId;
    private String typeName;
    private List<User> userList;

    public int getTypeId() {
        return typeId;
    }

    public void setTypeId(int typeId) {
        this.typeId = typeId;
    }

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String name) {
        this.typeName = name;
    }

    @Override
    public String toString() {
        return "Type{" +
                "typeId=" + typeId +
                ", typeName='" + typeName + '\'' +
                ", userList=" + userList +
                '}';
    }
}

此时一个type对应多个user如何是好,那么就需要在xml中定义

<resultMap id="getTypeByIdAndUsers" type="model.Type">
    <id column="type_id" property="typeId"/>
    <result column="type_name" property="typeName"/>
    <collection property="userList" ofType="model.User">
        <id column="user_id" property="userId"/>
        <result column="name" property="name"/>
        <result column="password" property="password"/>
    </collection>
</resultMap>

<select id="getTypeByIdAndUsers" resultMap="getTypeByIdAndUsers">
    select * from user natural join type where type_id = #{type_id};
</select>
发布了23 篇原创文章 · 获赞 1 · 访问量 521

猜你喜欢

转载自blog.csdn.net/qq_38783257/article/details/103115549
今日推荐