• 使用 resultMap 实现高级结果集映射


    resultMap 的基本配置项

      属性

        id 属性:resultMap 的唯一标识,此 id 值用于 select 元素 resultMap 属性的引用。
        type 属性:表示该 resultMap 的映射结果类型(通常是 Java 实体类)。

      子节点

        id 子节点:一般对应数据库中该行的主键 id,设置此项可以提升 MyBatis 性能。
        result 子节点:映射到 JavaBean 的某个 “简单类型” 属性,如基础数据类型、包装类等。

      子节点属性

        column 属性:表示从数据库中查询的字段名或别名。

        property 属性:表示查询出来的字段对应的值赋给实体对象的哪个属性。

      说明:子节点 id 和 result 均可实现最基本的结果集映射,将列映射到简单数据类型的属性。这两者唯一不同的是:在比较对象实例时 id 将作为结果集的标识属性。这有助于提高总体性能,特别是应用缓存和嵌套结果映射的时候。而若要实现高级结果映射,就需要学习下面两个配置项: association 和 collection。

    ssociation

      association:映射到 JavaBean 的某个 “复杂类型” 属性,比如 JavaBean 类,即 JavaBean 内部嵌套一个复杂数据类型(JavaBean)属性,这种情况就属于复杂类型的关联。但是需要注意: association 仅处理一对一的关联关系

      ssociation 的属性

        javaType 属性:完整 Java 类名或者别名。若映射到一个 JavaBean,则 MyBatis 通常会自行检测到其类型;若映射到一个 HashMap ,则应该明确指定 javaType,来确保所需行为。

         property 属性:映射数据库列的实体对象的属性。

      ssociation 的子元素

        id 子元素:一般对应数据库中该行的主键 id,设置此项可以提升 MyBatis 性能。

        result 子元素
            ◆ property 属性:映射数据库列的实体对象的属性。
            ◆ column 属性:数据库列名或别名。

      说明
         (1)在做结果映射的过程中,需要注意:要确保所有的列名都是唯一且无歧义的。
         (2)id 子元素在嵌套结果映射中扮演了非常重要的角色,应该指定一个或者多个属性来唯一标识这个结果集。实际上,即便没有指定 id, MyBatis 也会工作,但是会导致严重的性能开销,所以最好选择尽量少的属性来唯一标识结果,主键或者联合主键均可。

     案例根据用户角色 id 获取该角色下的用户列表

    (1)修改 User 类,增加角色属性 (private Role role) ,并增加相应的 getter 和 setter 方法。
    
          private Role role;   //复杂类型:用户角色
        
          public Role getRole() {
              return role;
          }
          public void setRole(Role role) {
              this.role = role;
          }
    
    (2)在 UserMapper.java 接口里增加根据角色 id 获取用户列表的方法。
    
        /**
         * 根据用户角色 id 获取该角色下的用户列表
         * @param roleId 用户角色 id
         * @return
         */
        public List<User> getUserListByRoleId(@Param("uRole")int roleId);
    
    (3)在 UserMapper.xml 里增加 id 为 getUserListByRoleId 的查询语句,该查询语句返回类型为 resultMap,并且外部引用的 resultMap 的类型为 User。
       说明:由于 User 对象内嵌 JavaBean 对象(role),因此需要使用 association 来实现结果映射。
    
        <!--根据用户角色 id 获取该角色下的用户列表 -->
        <select id="getUserListByRoleId" resultMap="userRoleResult"
            parameterType="int">
            SELECT u.* , r.id AS r_id , r.`roleCode` , r.`roleName`
            FROM `smbms_user` AS u,`smbms_role` AS r
            WHERE u.`userRole`=#{uRole} AND u.`userRole`=r.`id`
        </select>
    
        <resultMap type="user" id="userRoleResult">
            <id property="id" column="id" />
            <result property="userCode" column="userCode" />
            <result property="userName" column="userName" />
            <result property="userRole" column="userRole" />
    
            <association property="role" javaType="role">
                <id property="id" column="r_id" />
                <result property="roleCode" column="roleCode" />
                <result property="roleName" column="roleName" />
            </association>
        </resultMap>4)单元测试类使用 Junit 测试   
    
       @Test //测试根据用户角色 id 获取该角色下的用户列表
        public void testGetUserListByRoleId(){
              List<User> userList=new ArrayList<User>();
              userList=session.getMapper(UserMapper.class).getUserListByRoleId(2);
                
              //打印 用户角色 id 为 2 的用户有几个
              System.out.println("userList 的长度:"+userList.size());
              //使用 resultMap 实现复杂类型关联
              for (User user : userList) {
                    System.out.println("User:"+user.getUserName()+
                    "---Role:"+user.getRole().getId()+"---"+user.getRole().getRoleCode()+"---"+user.getRole().getRoleName());
              }
        }

     复用 association 的结果映射

      association 提供了的另一个属性: resultMap 通过这个属性可以扩展一个 resultMap 来进行联合映射,这样就可以使 role 结果映射重复使用。特别适合 association 的结果映射比较多的情况,当然,若不需要重用,也可按照上面代码的写法,直接嵌套这个联合结果映射,根据具体业务而定。

    //使用 resultMap 属性完成 association 的 role 映射结果的复用,修改 UserMapper.xml ,association 子节点上增加 resultMap 属性来引用外部的 resultMap。
    
    <!--根据用户角色 id 获取该角色下的用户列表 -->
        <select id="getUserListByRoleId" resultMap="userRoleResult"
            parameterType="int">
            SELECT u.* , r.id AS r_id , r.`roleCode` , r.`roleName`
            FROM `smbms_user` AS u,`smbms_role` AS r
            WHERE u.`userRole`=#{uRole} AND u.`userRole`=r.`id`
        </select>
    
        <resultMap type="user" id="userRoleResult">
            <id property="id" column="id" />
            <result property="userCode" column="userCode" />
            <result property="userName" column="userName" />
            <result property="userRole" column="userRole" />
    
            <association property="role" javaType="role" resultMap="roleResult" />
        </resultMap>
        
        <resultMap type="role" id="roleResult">
                <id property="id" column="r_id"/>
                <result property="roleCode" column="roleCode"/>
                <result property="roleName" column="roleName"/>
        </resultMap>

    collection

      collection 元素的作用和 association 元素的作用差不多一样,事实上,它们非常类似,也是映射到 JavaBean 的某个 “复杂类型” 属性,只不过这个属性是一个集合列表,即 JavaBean 内部嵌套一个复杂数据类型(集合)属性。和使用 association 元素一样,我付使用嵌套查询,或者从连接中嵌套结果集。

      collection 的属性

        ofType 属性:完整 Java 类名或者别名,即集合所包含的类型。

        property 属性:映射数据库列的实体对象的属性。

      collection 的子元素

        id 子元素:一般对应数据库中该行的主键 id,设置此项可以提升 MyBatis 性能。

        result 子元素
            ◆ property 属性:映射数据库列的实体对象的属性。
            ◆ column 属性:数据库列名或别名。

     案例获取指定用户的相关信息和地址列表

    (1)在 User 实体类中,增加地址列表属性 private List<Address> addressList ,并增加相应的 getter 和 setter 方法。User 对象内部嵌套了一个复杂数据类型的属性,addressList。
    
           private List<Address> addressList;  //用户地址列表
        
           public List<Address> getAddressList() {
               return addressList;
           }
           public void setAddressList(List<Address> addressList) {
               this.addressList = addressList;
           }
    
    (2)在 UserMapper.java 接口中增加根据用户 id 获取用户信息以及地址列表的方法。
    
           /**
         * 根据用户 id 获取指定用户的相关信息和地址列表
         * @param userId 用户 id
         * @return
         */
        public List<User> getAddressListByUserId(@Param("id")int userId);
    
    (3)在 UserMapper.xml 中增加 id 为 getAddressListByUserId 的查询语句,该 select 查询语句返回类型为 resultMap ,并且引用外部的 resultMap 的类型为 User。由于 User 对象内嵌集合对象(addressList) ,因此需要使用 collection 来实现结果映射。
    
    <!--根据用户 id 获取指定用户的相关信息和地址列表-->
        <select id="getAddressListByUserId" resultMap="userAddressResult" parameterType="int">
                SELECT u.*,a.`id` AS a_id ,a.`contact`,a.`addressDesc`,a.`postCode`,a.`tel` 
                FROM `smbms_user` u ,`smbms_address` a 
                WHERE u.`id`=a.`userId` AND u.`id`=#{id}
        </select>
        
        <resultMap type="user" id="userAddressResult">
                <id property="id" column="id"/>
                <result property="userCode" column="userCode"/>
                <result property="userName" column="userName"/>
                
            <collection property="addressList" ofType="address">
                <id property="id" column="a_id"/>
                <result property="postCode" column="postCode"/>
                <result property="tel" column="tel"/>
                <result property="contact" column="contact"/>
                <result property="addressDesc" column="addressDesc"/>
            </collection>
        </resultMap>4)单元测试类使用 Junit 测试     
    
    @Test //测试根据用户 id 获取指定用户的相关信息和地址列表
        public void testGetAddressListByUserId() {
            List<User> userList = new ArrayList<User>();
            userList = session.getMapper(UserMapper.class).getAddressListByUserId(1);
    
            for (User user : userList) {
                System.out.println("userList(include:addresslist) =====> userCode: " + user.getUserCode() + ", userName: "
                        + user.getUserName());
                for (Address address : user.getAddressList()) {
                    System.out.println("address ----> id: " + address.getId() + ", contact: " + address.getContact()
                            + ", addressDesc: " + address.getAddressDesc() + ", tel: " + address.getTel() + ", postCode: "
                            + address.getPostCode());
                }
            }
       }    

    复用 collection 的结果映射

      提取相应代码到一个 resultMap 中,给 collection 增加 resultMap 属性进行外部引用即可。
       <!--根据用户 id 获取指定用户的相关信息和地址列表-->
        <select id="getAddressListByUserId" resultMap="userAddressResult" parameterType="int">
                SELECT u.*,a.`id` AS a_id ,a.`contact`,a.`addressDesc`,a.`postCode`,a.`tel` 
                FROM `smbms_user` u ,`smbms_address` a 
                WHERE u.`id`=a.`userId` AND u.`id`=#{id}
        </select>
        
        <resultMap type="user" id="userAddressResult">
                <id property="id" column="id"/>
                <result property="userCode" column="userCode"/>
                <result property="userName" column="userName"/>
                
            <collection property="addressList" ofType="address" resultMap="addressResult"/>
        </resultMap>
        
        <resultMap type="address" id="addressResult">
                <id property="id" column="a_id"/>
                <result property="postCode" column="postCode"/>
                <result property="tel" column="tel"/>
                <result property="contact" column="contact"/>
                <result property="addressDesc" column="addressDesc"/>
        </resultMap>

  • 相关阅读:
    ssh实现免密码登录和文件传输
    linux后台执行程序相关命令
    orchestrator
    curl下载安装与使用
    goland使用
    mysql集群
    consul理解
    my.cnf
    数据库的表设计
    项目常见面试问题
  • 原文地址:https://www.cnblogs.com/wxdestiny/p/9772412.html
Copyright © 2020-2023  润新知