4.3 分步查询
🙋 为什么使用分步查询【分步查询优势】?
将多表连接查询,改为【分步单表查询】,从而提高程序运行效率
4.3.1 一对一的关联关系
👉用法案例
使用分步查询实现通过员工id获取员工信息及员工所属的部门信息,比如说1.通过员工id获取员工信息,2.通过员工信息中的部门id获得所属部门得信息(员工与部门是一对一的关系,即一个员工只能归属一个部门)
代码示例如下:
①在EmployeeMapper接口中定义实现通过员工id获取员工信息的方法
//使用分步查询实现通过员工id获取员工信息及员工所属的部门信息 //1.通过员工id获取员工信息 //2.通过员工信息中的部门id获得所属部门得信息 public Employee selectEmpByempId(int empId);
②在DeptMapper接口中定义实现通过从查出来的员工信息中的部门编号去查所属部门信息
//通过部门id查询所属部门得信息 public Dept selectDeptByDeptId(int deptId);
③在EmployeeMapper接口对应的映射文件书写相应的sql
<resultMap id="selectEmpByempIdResultMap" type="mybatis.pojo.Employee"> <id property="id" column="id"></id> <result property="lastName" column="last_name"></result> <result property="email" column="email"></result> <result property="salary" column="salary"></result> <!-- column="deptId" 设置分步查询SQL中需要得参数dept_Id;将此值传入到mybatis.mapper.DeptMapper中的selectDeptByDeptId()方法中 --> <association property="dept" select="mybatis.mapper.DeptMapper.selectDeptByDeptId" column="dept_Id" > </association> </resultMap> <select id="selectEmpByempId" resultMap="selectEmpByempIdResultMap"> SELECT `id`, `last_name`, `email`, `salary`, `dept_id` FROM `tbl_employee` WHERE `id`=#{empId}; </select>
④在DeptMapper接口对应的映射文件中书写相应的sql
<resultMap id="selectDeptByDeptIdResultMap" type="dept"> <id property="deptId" column="dpt_Id"></id> <result property="deptName" column="dpt_name"></result> </resultMap> <select id="selectDeptByDeptId" resultMap="selectDeptByDeptIdResultMap"> select dpt_Id, dpt_name from tbl_department where dpt_Id=#{dptId} </select>
⑤测试
@Test public void test02(){ try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通过SqlSessionFactory对象调用openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(); //获取EmployeeMapper的代理对象 EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class); Employee employee = employeeMapper.selectEmpByempId(2); System.out.println(employee); } catch (IOException e) { e.printStackTrace(); } }
4.3.2 一对多的关联关系
👉用法案例
通过部门id获取部门信息,及部门所属员工信息【使用分步查询来实现】,其中按1.通过部门id获取部门信息;2.通过部门id获取员工信息等这两个步骤完成分步查询
代码示例如下:
①在DeptMapper接口中书写查询通过部门id获取部门信息的方法
//通过部门id获取部门信息 public Dept showEmployeesByDeptIdBetter(int deptId);
②在DeptMapper接口对应的映射文件中书写相应的sql
<!-- type="dept" 设置映射类型为dept,为什么不是dept类的全称,因为我在配置文件给它起了别名 --> <resultMap id="showEmployeesByDeptIdBetterResultMap" type="dept"> <id property="deptId" column="dpt_id"></id> <result property="deptName" column="dpt_name"></result> <collection property="employees" select="mybatis.mapper.EmployeeMapper#selectEmployeeByempId" column="dpt_Id"> </collection> </resultMap> <select id="showEmployeesByDeptIdBetter" resultMap="showEmployeesByDeptIdBetterResultMap"> SELECT `dpt_id`, `dpt_name` FROM `tbl_department` WHERE `dpt_id`=#{dptId}; </select>
③在EmployeeMapper接口中书写查询通过部门id获取所属员工信息的方法
//通过部门id查询对应的员工信息 public Employee selectEmployeeByempId(int empId);
④在EmployeeMapper接口对应的映射文件中书写相应的sql
<select id="showEmployeesByDeptIdBetter" resultMap="showEmployeesByDeptIdBetterResultMap"> SELECT `dpt_id`, `dpt_name` FROM `tbl_department` WHERE `dpt_id`=#{dptId}; </select>
⑤测试
@Test //测试分步查询版(根据部门编号查询对应的部门信息,然后拿着部门编号去员工表里去找所属的员工信息) public void test05(){ try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通过SqlSessionFactory对象调用openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(); //获取EmployeeMapper的代理对象 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); Dept dept = deptMapper.showEmployeesByDeptId(1); System.out.println(dept); } catch (IOException e) { e.printStackTrace(); } }
4.3.3 扩展
如果使用分步查询时,需要传递给调用的查询中多个参数,则需要将多个参数封装成 Map来进行传递,语法如下:{k1=v1,k2=v2}
五、Mybatis如何使用延迟加载【懒加载】?
🙋什么是延迟加载?
需要时加载,不需要暂时不加载,如何理解?举个生活中的例子,就好比当你非常饥饿时,才会去吃饭
👉优势
可以提高程序运行效率
👉语法
🚀①全局设置
在核心配置文件中这样写,示例代码如下
<settings> <!-- 开启驼峰命名自动映射 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 开启全局延迟加载模式 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 关闭按需延迟加载模式,在3.4.2版本及以后该步骤可省略 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
👉用法案例
在核心配置文件开启全局延迟加载模式,借助8.6小结中的案例代码,演示全局延迟加载模式的效果
代码示例如下:
测试运行如下
try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通过SqlSessionFactory对象调用openSession(); SqlSession sqlSession = sqlSessionFactory.openSession(); //获取EmployeeMapper的代理对象 EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class); Employee employee = employeeMapper.selectEmpByempId(2); System.out.println("employee.getLastName() = "+employee.getLastName()); System.out.println("--------------------------------------"); System.out.println("employee.getDept() = "+employee.getDept()); } catch (IOException e) { e.printStackTrace(); }
🚀②局部设置
- fetchType
eager
:关闭局部延迟加载lazy
:开启局部延迟加载
👉用法案例
在上述案例中EmployeeMapper接口对应的映射文件里属性id的值为"selectEmpByempId"的sql设置关闭延迟加载(已经设置了全局延迟加载模式,这里再开启局部延迟加载,效果不明显,遂采用关闭局部延迟加载测试效果)
代码示例如下:
<resultMap id="selectEmpByempIdResultMap" type="mybatis.pojo.Employee"> <id property="id" column="id"></id> <result property="lastName" column="last_name"></result> <result property="email" column="email"></result> <result property="salary" column="salary"></result> <!-- column="deptId" 设置分步查询SQL中需要得参数dept_Id;将此值传入到mybatis.mapper.DeptMapper中的selectDeptByDeptId()方法中 --> <!-- fetchType="lazy" 为此方法设置局部延迟加载 --> <association property="dept" select="mybatis.mapper.DeptMapper.selectDeptByDeptId" column="dept_Id" fetchType="lazy" > </association> </resultMap> <select id="selectEmpByempId" resultMap="selectEmpByempIdResultMap"> SELECT `id`, `last_name`, `email`, `salary`, `dept_id` FROM `tbl_employee` WHERE `id`=#{empId}; </select>
运行测试如下