学习mybatis3的第5天
场景二:之前是查员工的时候,顺序得到这个员工所在的部门。(一对一)现在变一下,是查部门的时候,把这个部门的所有员工查出来。(一对多)
Collection的讲解。
使用多表联查的形式:
SELECT
d.id did, d.dept_name dept_name,
e.id eid,e.last_name last_name,
e.email email, e.gender gender
FROM `tbl_dept` d
LEFT JOIN `tbl_employee` e
ON d.id = e.d_id
WHERE d.id = 1;
这些就是现在查出来的列。
did dept_name eid last_name email gender
下面这些是javaBean的属性名。
1、写接口:DepartmentMapper
public interface DepartmentMapper {
public Department getDeptById(Integer id);
//根据部门id,查出这个部门信息,以及该部门对应的所有员工信息。
public Department getDeptByIdPlus(Integer id);
}
2、对应的sql映射配置文件:(关键)
方式一:使用collection嵌套的意思。
<resultMap id="MyDept" type="com.rtl.mybatis.bean.Department">
<id column="did" property="id"></id>
<result column="dept_name" property="departmentName"></result>
<collection property="emps" ofType="com.rtl.mybatis.bean.Employee">
<id column="eid" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="email" property="email"></result>
<result column="gender" property="gender"></result>
</collection>
</resultMap>
<select id="getDeptByIdPlus" resultMap="MyDept">
SELECT
d.id did, d.dept_name dept_name,
e.id eid,e.last_name last_name,
e.email email, e.gender gender
FROM `tbl_dept` d
LEFT JOIN `tbl_employee` e
ON d.id = e.d_id
WHERE d.id = #{id};
</select>
方式二:使用collection分步查询。
sql:
第一步:
SELECT * FROM tbl_dept WHERE id = 1;
第二步:
SELECT * FROM tbl_employee WHERE d_id = 1;
1、先在接口里面去声明方法:DepartmentMapper
public Department getDeptByIdStep(Integer id);
2、去写sql映射配置文件DepartmentMapper.xml
因为分步查询里面的第二步就是按照部门id去查这个部门对应的所有的员工。
3、所以要先在EmployeeMapperPlus这里面去添加方法。
public List<Employee> getEmpsByDeptId(Integer deptId);
4、去完善EmployeeMapperPlus.xml
<select id="getEmpsByDeptId" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee where d_id = #{deptId}
</select>
5、写好这些之后,再来完善:DepartmentMapper.xml(关键!!)
使用collection实现分布查询。
<resultMap id="MyDeptStep" type="com.rtl.mybatis.bean.Department">
<id column="id" property="id"></id>
<result column="dept_name" property="departmentName"></result>
<collection property="emps" select="com.rtl.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="id"></collection>
</resultMap>
<select id="getDeptByIdStep" resultMap="MyDeptStep">
SELECT id,dept_name FROM tbl_dept WHERE id = #{id};
</select>
6、测试类:
//测试查询:写的是resultMap,查询一个部门的所有员工(一对多)的时候,使用collection标签。分步查询的形式
@Test
public void test16() throws IOException {
//(16,17,18行)1、根据这个全局的mybatis-config.xml配置文件生成一个SqlSessionFactory对象。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、根据SqlSessionFactory对象获取sqlSession实例,整个实例可以执行已经映射的sql语句。
SqlSession openSession = sqlSessionFactory.openSession();
try {
//获取接口EmployeeMapper的实现类对象
DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class);
Department department = mapper.getDeptByIdStep(1);
System.out.println(department);
List<Employee> emps = department.getEmps();
for (Employee emp : emps) {
System.out.println(emp);
}
}finally {
openSession.close();
}
}
注意。xml的内容这样也是可以的:
<resultMap id="MyDeptStep" type="com.rtl.mybatis.bean.Department">
<id column="id" property="id"></id>
<result column="dept_name" property="departmentName"></result>
<collection property="emps" select="com.rtl.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}"></collection>
</resultMap>
其中这里的column的意思就是,它前面的select标签里面的查询语句需要的参数,都是由这个column来提供。
假设前面的查询语句需要两个参数的话,那就以map的形式传递过来。
clomun={deptId=id}
右边的id是第一步从部门表里面查出来的实际值。部门id
赋值给第二部查询需要的参数。
这样中间的查询方法,里面的参数才有值了。
动态SQL
之前的拼串SQL非常的复杂。
需要学习以下几个标签:
if
choose(when otherwise)
trim (where set)
foreach
1、创建接口:EmployeeMapperDynamicSQL
package com.rtl.mybatis.dao;
public interface EmployeeMapperDynamicSQL {
}
2、创建sql映射配置文件
<?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">
<mapper namespace="com.rtl.mybatis.dao.EmployeeMapperDynamicSQL">
</mapper>
学习if标签 判断
需求:
要求查询的时候,携带了哪个字段就带上这个字段的值。如果是null,就不要。
1、在接口EmployeeMapperDynamicSQL里面提供方法。
public List<Employee> getEmpsByConditionIf(Employee employee);
2、修改EmployeeMapperDynamicSQL.xml
<select id="getEmpsByConditionIf" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee
where id=#{id} and last_name=#{lastName}
and email=#{email} and gender=#{gender}
</select>
改进:
where后面的东西不能写死。
<select id="getEmpsByConditionIf" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee
where
<if test="id!=null">
id=#{id}
</if>
<if test="last_name!=null and last_name!=''">
and last_name like #{lastName}
</if>
<if test="email!=null and email.trim()!=''">
and email=#{email}
</if>
<if test="gender==0 or gender == 1">
and gender=#{gender}
</if>
</select>
我们发现gender在javaBean里面是String数据类型,但是写的时候可以直接
gender == 0 or gender == 1
因为OGNL会默认进行字符串和数字的转换操作。
3、现在去写测试类。
@Test
public void test17() throws IOException {
//(16,17,18行)1、根据这个全局的mybatis-config.xml配置文件生成一个SqlSessionFactory对象。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、根据SqlSessionFactory对象获取sqlSession实例,整个实例可以执行已经映射的sql语句。
SqlSession openSession = sqlSessionFactory.openSession();
try {
//获取接口EmployeeMapper的实现类对象
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
Employee employee = new Employee(1, "jerry", null, null);
List<Employee> emps = mapper.getEmpsByConditionIf(employee);
for (Employee emp : emps) {
System.out.println(emp);
}
}finally {
openSession.close();
}
}
但是这样写会有问题。
问题:当第一个id 是null的时候
那么sql就变成这样了:
select * from tbl_emp
where and last_name lile “jerry”
直接就报语法错误了。
最终版:建议加上where 标签比较好。
<select id="getEmpsByConditionIf" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee
<where>
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null and lastName!=''">
and last_name like #{lastName}
</if>
<if test="email!=null and email.trim()!=''">
and email=#{email}
</if>
<if test="gender==0 or gender == 1">
and gender=#{gender}
</if>
</where>
</select>
学习set标签。
1、在接口里面定义一个更新方法。
不要全字段的更新,而是,你带了哪一列的值就更新哪一列。如果这一列是null,那就维持原先的值。
public void updateEmp(Employee employee);
2、使用set标签:
<update id="updateEmp">
update tbl_employee
<set>
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id = #{id}
</update>
测试类:
@Test
public void test18() throws IOException {
//(16,17,18行)1、根据这个全局的mybatis-config.xml配置文件生成一个SqlSessionFactory对象。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、根据SqlSessionFactory对象获取sqlSession实例,整个实例可以执行已经映射的sql语句。
SqlSession openSession = sqlSessionFactory.openSession();
try {
//获取接口EmployeeMapper的实现类对象
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
Employee employee = new Employee(1, "jerry1", "jerry@163.com", null);
mapper.updateEmp(employee);
openSession.commit();
}finally {
openSession.close();
}
}
使用foreach查询id是给定的集合中
就是 where id in(1,2,3)这种
1、接口中添加方法。
public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);
2、修改xml
普通写法:不使用foreach进行遍历。
<select id="getEmpsByConditionForeach" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee where id in(1,2,3)
</select>
使用foreach进行遍历。
<select id="getEmpsByConditionForeach" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee where id in(
<foreach collection="ids" item="item_id" separator=",">
#{item_id}
</foreach>
)
</select>
collection代表指定要遍历的集合。
item将当前遍历的元素赋值给指定的变量。
separator代表每个元素之间的分隔符
写得好看一点,把两边的括号去掉。
<select id="getEmpsByConditionForeach" resultType="com.rtl.mybatis.bean.Employee">
select * from tbl_employee where id in
<foreach collection="ids" item="item_id" separator="," open="(" close=")">
#{item_id}
</foreach>
</select>
open:遍历出所有结果拼接一个开始的字符。
close:遍历出所有结果拼接一个结束的字符。
使用foreach进行批量插入数据。(难度)
1、修改接口
public void addEmps(@Param("emps") List<Employee> emps);
2、修改mapper.xml
正常的sql;
INSERT INTO `tbl_employee`(last_name,email,gender,d_id)
VALUES("tom","tom@123.com",'1',1),("frank","frank@123.com",'0',1);
使用foreach版本的:
<insert id="addEmps">
INSERT INTO `tbl_employee`(last_name,email,gender,d_id)
VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
测试类:
//测试 使用foreach实现 批量插入数据
@Test
public void test20() throws IOException {
//(16,17,18行)1、根据这个全局的mybatis-config.xml配置文件生成一个SqlSessionFactory对象。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、根据SqlSessionFactory对象获取sqlSession实例,整个实例可以执行已经映射的sql语句。
SqlSession openSession = sqlSessionFactory.openSession();
try {
//获取接口EmployeeMapper的实现类对象
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
List<Employee> list = Arrays.asList(
new Employee(null, "tom1", "tom2@123.com", "1",new Department(1,"开发部")),
new Employee(null, "tom2", "tom2@123.com", "1",new Department(2,"测试部")));
mapper.addEmps(list);
openSession.commit();
}finally {
openSession.close();
}
}
mybatis里面两个重要的内置参数。
1、_parameter
代表接口方法里面的整个参数
add(Integer id) _parameter代表id
adds(List emps) _parameter代表emps