MyBatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的是一对一,collection指的是一对多查询。在MyBatis配置文件中,可以配置是否请用延迟加载lazy LoadingEnabled=true|false。
首先要搞清楚什么是延迟加载和立即加载:
延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)。
立即加载:不管用不用,只要一调用方法,马上发起查询。
使用场景:在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载。
关联-association
集合-collection
理解了延迟加载的特性以后再看Mybatis中如何实现查询方法的延迟加载,在MyBatis 的配置文件中通过设置settings的lazyLoadingEnabled属性为true进行开启全局的延迟加载,
通过aggressiveLazyLoading属性开启立即加载。看一下官网的介绍,然后通过一个实例来实现Mybatis的延迟加载,在例子中我们展现一对多表关系情况下,
通过实现查询用户信息同时查询出该用户所拥有的账户信息的功能展示一下延迟加载的实现方式以及延迟加载和立即加载的结果的不同之处。
|
实体类(省-区):
1 public class Province { 2 //省的id 3 private Integer proId; 4 //省的名称 5 private String proName; 6 //市 7 private List<City> city; 8 } 9 10 public class City { 11 //市的id 12 private Integer ciId; 13 //市的名称 14 private String ciName; 15 } 16 //省略gerter,setter方法,一定要有空参构造
接口类(CascadeInterface--CityMapper):
public interface CityMapper { //通过省的id查询数据库匹配所有的城市 public List<CityMapper> listCityById(Integer id); } public interface CascadeInterface { //查询省信息 public List<Province> listProvince(); }
mybatis-config.xml配置中开启延迟加载
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--加载数据库配置文件--> <properties resource="db.properties"/> <settings> <!--开启全局的懒加载--> <setting name="lazyLoadingEnabled" value="true"/> <!--关闭立即加载,其实不用配置,默认为false--> <setting name="aggressiveLazyLoading" value="false"/> <!--打印执行过程,由于一级缓存是自动开启的,不需要手动开启--> <setting name="logImpl" value="STDOUT_LOGGING"/> <!--开启二级缓存--> <setting name="cacheEnabled" value="true"/> </settings> <!--给ccom.Charon.enty包下所有的实体类指定别名--> <typeAliases> <package name="com.Charon.enty"/> </typeAliases> <!-- 数据库连接环境的配置 --> <environments default="development"> <environment id="development"> <!-- 事务管理器JDBC --> <transactionManager type="JDBC" /> <!-- 数据源--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <mappers> <!--必须全包名,不然找不到--> <mapper resource="com/Charon/dao/userMapper.xml"></mapper> <mapper resource="com/Charon/dao/CascadenMapper.xml"></mapper> <mapper resource="com/Charon/dao/cityMapper.xml"></mapper> </mappers> </configuration>
在provinceMapper.xml中配置listCityById方法的映射
<?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"> <!-- mytatis 的接口映射文件--> <mapper namespace="com.Charon.dao.CascadeInterface"> <!--返回值类型为Province实体类--> <resultMap id="CityAll" type="province"> <id property="proId" column="PROV_ID"></id> <result property="proName" column="NAME"></result> <!--property:Province实体类类中的city属性--> <!--column:映射数据库字段名称,唯一标识--> <!--ofType:返回类型为City--> <!--javaType:传入值类型为ArrayList--> <!--select:调用CityMapper接口下的listCityById方法--> <collection property="city" column="proId" ofType="com.Charon.enty.City" javaType="ArrayList" select="com.Charon.dao.CityMapper.listCityById"> <!--给City类中的属性赋值--> <id property="coId" column="PROV_ID"></id> <result column="NAME" property="coName"></result> </collection> </resultMap> <!--返回自定义类型--> <select id="listProvince" resultMap="CityAll"> SELECT PROV_ID proId, NAME proName FROM base_province </select> </mapper>
主要的功能实现位于 <collection property="city" ofType="com.Charon.enty.City" column="PROV_ID" select="com.Charon.dao.CityMapper.listCityById"/>中,
对市的列表信息通过collection集合来映射,通过select指定集合中的每个元素如何查询,
在本例中select的属性值为cityMapper.xml文件的namespace=com.Charon.dao.CityMapper路径以及指定该映射文件下的listCityById方法,
通过这个唯一标识指定集合中元素的查找方式。因为在这里需要用到根据用户ID查找市,所以需要同时配置一下listCityById方法的实现。
cityMapper.xml中配置collection中select属性所使用的方法
<select id="listCityById" resultType="city"> SELECT base_city.PROV_ID ciId, base_city.NAME ciName FROM base_city where base_city.PROV_ID = #{id} </select>
代码测试:
当我们把for循环注释掉,当前程序只向数据库发送了一个请求,只查询了省的信息
通过for循环打印查询的数据,使用数据,这时候因为使用了数据所以将查询市的信息,我们发现省和市查询都进行了执行
Emp-Dept实体类:
public class Emp { private int id; private String user_name; private String job; private int marid; private double salary; private int deptid;
//入职时间 private String hiredate; private Dept dept; } public class Dept { private int id;
//部门名称 private String depts;
//部门领导 private String emp_name; }
emp.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.Charon.dao.EmpInterface1"> <!--级联查询--> <resultMap id="listEmp" type="emp">
<!--id是唯一标识,不可少-->
<id column="id" property="id"></id> <result column="user_name" property="user_name"></result> <result column="job" property="job"></result> <result column="salary" property="salary"></result> <!--使用association实现级联查询--> <!--<result column="dept" property="dept.depts"></result>--> <!--第一个property(dept)是emp 类中的;columbn:数据库中的字段,property:Dept中的字段--> <association property="dept" javaType="com.Charon.enty.Dept"> <result column="type" property="depts"></result> </association> </resultMap> <!--查询用户所有信息包含部门名称-->
<select id="listEmpanddept" resultMap="listEmp"> SELECT empuser.id id, empuser.user_name user_name, empuser.job job, empuser.salary salary, empusertype.type from empuser, empusertype where empuser.deptid = empusertype.id </select> </mapper>
测试代码:
/** * 级联查询:association * 查询用户的 姓名,薪资,部门,职位 */ @Test public void test1(){ EmpInterface1 mapper = session.getMapper(EmpInterface1.class); List<Emp> emps = mapper.listEmpanddept(); for (int i = 0; i < emps.size(); i++) { Emp emp = emps.get(i);
System.out.println("姓名:"+emp.getUser_name()+"\t职位:"+emp.getJob()+"\t部门:"+emp.getDept().getDepts());
} }
结果:
Mybatis中collection和association的使用区别
原文:https://www.cnblogs.com/zhuzhu-you/p/13892794.html