MyBaits | 映射文件之参数处理

一、MyBaits的增删改查
1. 介绍
输入映射
这里我先介绍一下输入映射,是在映射文件中通过 parameterType
指定输入参数的类型,类型可以是简单类型、Hashmap
、POJO
的包装类型。在实际操作中,一般我们会在 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 语句都需要提交数据,如果只是查询操作,则可以不必提交
- 如果创建
openSession()
没有加参数,则在执行 sql 的语句后提交数据,可以使用sqlSession.commit()
- 如果创建 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. 传入多个参数
我们先来看一个情景,如果需要传入 id
和 lastName
两个参数
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
,值为你 传入的参数的值
的形式来保存数据,此时 ma
解决方案
方案一
我们以上述的例子为例,我们可以直接传入 #{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}