首页 > 其他 > 详细

Mybatis中collection和association的使用区别

时间:2020-10-28 19:51:20      阅读:82      评论:0      收藏:0      [点我收藏+]

文章简介:

MyBatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的是一对一,collection指的是一对多查询。在MyBatis配置文件中,可以配置是否请用延迟加载lazy LoadingEnabled=true|false。

 


 

 

首先要搞清楚什么是延迟加载和立即加载:

  延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)。

  立即加载:不管用不用,只要一调用方法,马上发起查询。

  使用场景:在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载。

  关联-association
    集合-collection


 

  理解了延迟加载的特性以后再看Mybatis中如何实现查询方法的延迟加载,在MyBatis 的配置文件中通过设置settings的lazyLoadingEnabled属性为true进行开启全局的延迟加载,

  通过aggressiveLazyLoading属性开启立即加载。看一下官网的介绍,然后通过一个实例来实现Mybatis的延迟加载,在例子中我们展现一对多表关系情况下,

  通过实现查询用户信息同时查询出该用户所拥有的账户信息的功能展示一下延迟加载的实现方式以及延迟加载和立即加载的结果的不同之处。

lazyLoadingEnabled 延迟加载的全局开关,当开启时,所有关联对象都会延迟加载,在特定关联关系中可通过设置fatchType属性来覆盖该项的开关状态 true/false true
aggressiveLazyLoading 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之每种属性将会按需加载 true/false 版本3.4.1 (不包含)
之前 true,之后 false

 

 

 

 


 

代码测试:(一对多collection)

实体类(省-区):

 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循环打印查询的数据,使用数据,这时候因为使用了数据所以将查询市的信息,我们发现省和市查询都进行了执行

 

 技术分享图片


 

 代码测试(一对一association)

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!