MyBaits | 映射文件之参数处理

一、MyBaits的增删改查

1. 介绍

输入映射

这里我先介绍一下输入映射,是在映射文件中通过 parameterType 指定输入参数的类型,类型可以是简单类型、HashmapPOJO 的包装类型。在实际操作中,一般我们会在 parameterType 属性中传入 POJO 的类名。如果是通过输入条件进行查询,我们只需要传入对应的 POJO 中的属性即可

输出映射

输出映射就是 sql 语句查询结束后返回的结果类型,在映射文件中通过 resultType 来显示输出的结果类型,不过一般可以不用设置 resultType,MyBatis 会自己帮我们输出。另外还可以使用 resultMap,这种配置方式可以用于各种复杂的映射方式,比如一对多,多对多等等,在后面的文章中会加以介绍

2. 使用 resultType 配置实现增删改查

①.首先我们定义一个 POJO 类:Employee.java

public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
        ......
}


②. 然后我们定义一个接口类:EmployeeMapper.java,该接口包含了对 Employee 的增删改查操作

public interface EmployeeMapper {

    public void addEmployee(Employee employee);

    public void updateEmployee(Employee employee);

    public long deleteEmployee(Integer id);

    public Employee getEmployee(Integer id);

}


③. 配置 EmployeeMapper.xml,这里我就只对增加操作加以说明,其他三种操作与之类似

<mapper namespace="edu.just.mybatis.dao.EmployeeMapper">
    <select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
        select id, last_name lastName, email, gender from employee where id = #{id}
    </select>
</mapper>
  • namespace:指定为你要实现的接口的全类名
  • id:唯一标识 resultType: 返回值类型
  • parameterType:是传入的参数的类型,可以使用别名,如果返回的是一个集合, 则写集合中元素的类型,比如 Employee, mybaits 会自动帮你把该类的对象放入集合中并返回
  • resultType:返回查询结果的类型,没有指定别名的情况下,使用全类名,当然也可以省略

④. 写一个测试语句,使用接口定义的方法

@Test
public void testGetEmployee() throws IOException {
    //1. 获取 sqlSessionFactory 对象
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactoty();

    //2. 获取 sqlSession 对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    try {
        //3. 获取接口的实现类对象, 会为接口自动创建一个代理对象, 代理对象去执行增、删、改、查
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmployee(1);
        System.out.println(employee);
    } finally {
        sqlSession.close();
    }
}

这里需要注意的是:如果涉及到对数据库数据本身的操作,针对增删改,每次执行完 sql 语句都需要提交数据,如果只是查询操作,则可以不必提交
1. 如果创建 openSession() 没有加参数,则在执行 sql 的语句后提交数据,可以使用 sqlSession.commit()
2. 如果创建 openSession(true), 则不需要提交数据

3. 其他情况

3.1 获取自增主键的值

在配置文件中将 useGeneratedKeys 属性设置为 true,同时 keyProperty 属性指定将获取的主键值赋给 JavaBean 的哪个属性

<insert id="addEmployee" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">
    Insert into employee(last_name, email, gender) values(#{lastName}, #{email}, #{gender})
</insert>

该配置表示将主键值赋给 Employee 的 id 属性,在测试文件中如果输出 id,即为当前查询结果的主键值

3.2 返回 List 集合的操作

首先在接口类中添加返回集合的方法

public List<Employee> getEmployees(String lastName);

然后在 sql 映射文件中配置,此时 resultType 的类型依旧是 Employee,因为对应的是集合中参数的类型

<select id="getEmployees" resultType="Employee">
    select * from employee where last_name like #{lastName}
</select>

输出如下

[Employee [id=7, lastName=null, email=lkj@123.com, gender=1], 
Employee [id=13, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=14, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=15, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=16, lastName=null, email=lkj@123.com, gender=2]]


3.3 返回一个封装多个记录的 Map 集合

@MapKey() 告诉 mybatis 封装这个 map 时候使用哪个POJO 属性作为 key

@MapKey("id")
public Map<Integer, Employee> getEmployee3(Integer id);

配置 sql 映射文件,注意此时 resultType 类型依然是 Employee,即表示返回的类型依旧是 Employee

<select id="getEmployee3" resultType="Employee">
    select id, last_name lastName, email, gender from employee where id > #{id}
</select>

输出

{16=Employee [id=16, lastName=lkj, email=lkj@123.com, gender=2], 
17=Employee [id=17, lastName=lkj, email=lkj@123.com, gender=2], 
2=Employee [id=2, lastName=Peter, email=peter@qq.com, gender=1], 
19=Employee [id=19, lastName=lkj, email=lkj@123.com, gender=2], 
20=Employee [id=20, lastName=lkj, email=lkj@123.com, gender=2]}


二、对参数进行处理

1. 传入单个参数

传入单个参数时,${xxx} 里面的参数名和属性名无关,比如你占位符设置为 #{id},此时当然可以查询出结果。但是如果你设置为 #{id123},同样查询出结果, 但是如果什么都不填, 则会报错

<select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
       select id, last_name lastName, email, gender from employee where id = #{id123} 
</select>


2. 传入多个参数

我们先来看一个情景,如果需要传入 idlastName 两个参数

public Employee getEmployee2(Integer id, String lastName);

sql 的配置文件是这样设置的

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
      id = #{id} and last_name = #{lastName}
</select>

此时会出这样的错误:Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

原因就是当 sql 语句传入不止一个参数时, MyBatis 会做特殊处理, 多个参数会被封装到一个 Map 对象 map 中,当你每传入一个参数,map 对象会将参数以键为 param1, param2...paramN,值为你 传入的参数的值 的形式来保存数据,此时如果你传入的还是类似 #{id}#{name} 之类的参数,那么肯定会报错

解决方案

方案一
我们以上述的例子为例,我们可以直接传入 #{param1},#{param2} 等参数

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{param1} and last_name = #{param2}
</select>


方案二
我们在接口定义的方法处,使用 @Param() 标注给方法中的参数起名字,其实本质上也是放在 Map 和对象 map 中

public Employee getEmployee2(@Param("id")Integer id, @Param("lastName")String lastName);

我们可以这样给传入的参数赋值,这时 map 中的 key 变为了 id, lastName, param1, param2。因此我们可以直接在 #{} 中传入我们自己命名的值。当然就算传入 #{param1} 之类的也是可以的。

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{id} and last_name = #{lastName}
</select>


三、${} 和 #{} 的区别

#{}:是以预编译的形式,将参数设置到 sql 语句中,多用于 where 语句后面的填充位,
${}:取出的值直接拼接在 sql 语句中,多用于分表的 sql 语句,会有线程安全的问题

关于 #{} 的使用我不加以赘述,下面举例说明 ${} 用于分表的操作语句

select * from ${year}_table where xxx
select * from table order by ${xxx} ${xxx}

猜你喜欢

转载自blog.csdn.net/babycan5/article/details/81437532