这里我先介绍一下输入映射,是在映射文件中通过 parameterType
指定输入参数的类型,类型可以是简单类型、Hashmap
、POJO
的包装类型。在实际操作中,一般我们会在 parameterType
属性中传入 POJO 的类名。如果是通过输入条件进行查询,我们只需要传入对应的 POJO 中的属性即可
输出映射就是 sql 语句查询结束后返回的结果类型,在映射文件中通过 resultType
来显示输出的结果类型,不过一般可以不用设置 resultType
,MyBatis 会自己帮我们输出。另外还可以使用 resultMap
,这种配置方式可以用于各种复杂的映射方式,比如一对多,多对多等等,在后面的文章中会加以介绍
①.首先我们定义一个 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()
在配置文件中将 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,即为当前查询结果的主键值
首先在接口类中添加返回集合的方法
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]]
@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]}
传入单个参数时,${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>
我们先来看一个情景,如果需要传入 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
,值为你 传入的参数的值
的形式来保存数据,此时如果你传入的还是类似 #{id}
,#{name}
之类的参数,那么肯定会报错
#####c解决方案
方案一
我们以上述的例子为例,我们可以直接传入 #{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}