MyBatis(三)(2)+https://developer.aliyun.com/article/1556670
6.2.3 一对多映射处理
DeptMapper.xml
<?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.atguigu.mybatis.mapper.DeptMapper"> <!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);--> <select id="getEmpAndDeptByStepTwo" resultType="Dept"> select * from t_dept where did = #{did} </select> <resultMap id="deptAndEmpResultMap" type="Dept"> <id property="did" column="did"></id> <result property="deptName" column="dept_name"></result> <!-- collection:处理一对多的映射关系 ofType:表示该属性所对应的集合中存储数据的类型 --> <collection property="emps" ofType="Emp"> <id property="eid" column="eid"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> <result property="email" column="email"></result> </collection> </resultMap> <!--Dept getDeptAndEmp(@Param("did") Integer did);--> <select id="getDeptAndEmp" resultMap="deptAndEmpResultMap"> select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did} </select> <resultMap id="deptAndEmpByStepResultMap" type="Dept"> <id property="did" column="did"></id> <result property="deptName" column="dept_name"></result> <collection property="emps" select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo" column="did" fetchType="eager"></collection> </resultMap> <!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);--> <select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap"> select * from t_dept where did = #{did} </select> </mapper>
public class Dept { private Integer did; private String deptName; //添加这个 private List<Emp> emps; //...构造器、get、set方法等 }
6.2.3.1 collection
- collection:用来处理一对多的映射关系
- ofType:表示该属性对饮的集合中存储的数据的类型
<resultMap id="DeptAndEmpResultMap" type="Dept"> <id property="did" column="did"></id> <result property="deptName" column="dept_name"></result> <collection property="emps" ofType="Emp"> <id property="eid" column="eid"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> <result property="email" column="email"></result> </collection> </resultMap> <!--Dept getDeptAndEmp(@Param("did") Integer did);--> <select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap"> select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did} </select>
6.2.3.2 分步查询
1. 查询部门信息
/** * 通过分步查询,查询部门及对应的所有员工信息 * 分步查询第一步:查询部门信息 * @param did * @return com.atguigu.mybatis.pojo.Dept */ Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept"> <id property="did" column="did"></id> <result property="deptName" column="dept_name"></result> <collection property="emps" select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo" column="did"></collection> </resultMap> <!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);--> <select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap"> select * from t_dept where did = #{did} </select>
2. 根据部门id查询部门中的所有员工
/** * 通过分步查询,查询部门及对应的所有员工信息 * 分步查询第二步:根据部门id查询部门中的所有员工 * @param did * @return java.util.List<com.atguigu.mybatis.pojo.Emp> */ List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);--> <select id="getDeptAndEmpByStepTwo" resultType="Emp"> select * from t_emp where did = #{did} </select>
6.2.4 延迟加载
分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
- aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
- 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
<settings> <!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> </settings>
@Test public void getEmpAndDeptByStepOne() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDeptByStepOne(1); System.out.println(emp.getEmpName()); }
关闭延迟加载,两条SQL语句都运行了
开启延迟加载,只运行获取emp的SQL语句
@Test public void getEmpAndDeptByStepOne() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDeptByStepOne(1); System.out.println(emp.getEmpName()); System.out.println("----------------"); System.out.println(emp.getDept()); }
开启后,需要用到查询dept的时候才会调用相应的SQL语句
fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”
<resultMap id="empAndDeptByStepResultMap" type="Emp"> <id property="eid" column="eid"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> <result property="email" column="email"></result> <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did" fetchType="lazy"></association> </resultMap>
7. 动态SQL
Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题
7.1 if
- if标签可通过test属性(即传递过来的数据)的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
- 在where后面添加一个恒成立条件
1=1
- 这个恒成立条件并不会影响查询的结果
- 这个
1=1
可以用来拼接and
语句,例如:当empName为null时 - 如果不加上恒成立条件,则SQL语句为
select * from t_emp where and age = ? and sex = ? and email = ?
,此时where
会与and
连用,SQL语句会报错
- 如果加上一个恒成立条件,则SQL语句为
select * from t_emp where 1= 1 and age = ? and sex = ? and email = ?
,此时不报错
<!--List<Emp> getEmpByCondition(Emp emp);--> <select id="getEmpByCondition" resultType="Emp"> select * from t_emp where 1=1 <if test="empName != null and empName !=''"> and emp_name = #{empName} </if> <if test="age != null and age !=''"> and age = #{age} </if> <if test="sex != null and sex !=''"> and sex = #{sex} </if> <if test="email != null and email !=''"> and email = #{email} </if> </select>
@Test public void testGetEmpByCondition(){ SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class); List<Emp> list = mapper.getEmpByCondition(new Emp(null, "", null, "", null)); System.out.println(list); }
7.2 where
where和if一般结合使用:
- 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字 ;
- 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉 。
<!--List<Emp> getEmpByCondition(Emp emp);--> <select id="getEmpByCondition" resultType="Emp"> select * from t_emp <where> <if test="empName != null and empName !=''"> emp_name = #{empName} </if> <if test="age != null and age !=''"> and age = #{age} </if> <if test="sex != null and sex !=''"> and sex = #{sex} </if> <if test="email != null and email !=''"> and email = #{email} </if> </where> </select>
注意:where标签不能去掉条件后多余的and/or
<!--这种用法是错误的,只能去掉条件前面的and/or,条件后面的不行--> <if test="empName != null and empName !=''"> emp_name = #{empName} and </if> <if test="age != null and age !=''"> age = #{age} </if>
7.3 trim
trim用于去掉或添加标签中的内容
常用属性:
- prefix:在trim标签中的内容的前面添加某些内容
- suffix:在trim标签中的内容的后面添加某些内容
- prefixOverrides:在trim标签中的内容的前面去掉某些内容
- suffixOverrides:在trim标签中的内容的后面去掉某些内容
若trim中的标签都不满足条件,则trim标签没有任何效果,也就是只剩下select * from t_emp
<!--List<Emp> getEmpByCondition(Emp emp);--> <select id="getEmpByCondition" resultType="Emp"> select * from t_emp <trim prefix="where" suffixOverrides="and|or"> <if test="empName != null and empName !=''"> emp_name = #{empName} and </if> <if test="age != null and age !=''"> age = #{age} and </if> <if test="sex != null and sex !=''"> sex = #{sex} or </if> <if test="email != null and email !=''"> email = #{email} </if> </trim> </select>
//测试类 @Test public void getEmpByCondition() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class); List<Emp> emps= mapper.getEmpByCondition(new Emp(null, "张三", null, null, null, null)); System.out.println(emps); }
MyBatis(三)(2)+https://developer.aliyun.com/article/1556674