1、association属性(关联的嵌套映射)

第一个属性是“关联的嵌套映射”,该属性的标签名称为“association”。在resultMap中,当映射type为Java包装类时,可能会遇到包装类中含有其他Java包装类的属性,这里resultMap提供了association标签来定义结果集中包含的其他结果集。

【示例】查询订单信息(Order),并获取关联的用户信息(User)。

(1)在数据库中创建用户信息表(tb_user)和订单信息表(tb_order)。

-- 创建“用户信息”数据表
CREATE TABLE IF NOT EXISTS tb_user
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',blog_url VARCHAR(50) NOT NULL COMMENT '博客地址',remark VARCHAR(50) COMMENT '备注',create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间'
) COMMENT = '用户信息表';-- 添加数据
INSERT INTO tb_user(user_name,blog_url,remark) VALUES('pan_junbiao的博客','https://blog.csdn.net/pan_junbiao','您好,欢迎访问 pan_junbiao的博客');
-- 创建“订单信息”数据表
CREATE TABLE IF NOT EXISTS tb_order
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '订单编号',order_no VARCHAR(50) NOT NULL COMMENT '订单单号',product_count INT DEFAULT '0' COMMENT '商品数量',price_total DECIMAL(9,2) DEFAULT '0' COMMENT '商品总价',user_id INT NOT NULL COMMENT '订单用户',create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间'
) COMMENT = '订单信息表';-- 添加数据
INSERT INTO tb_order(order_no,product_count,price_total,user_id) VALUE('T20191209001',5,14295,1)

(2)创建用户信息持久化类(User.java)和订单信息持久化类(Order.java)。

package com.pjb.mybatis.po;import java.io.Serializable;
import java.util.Date;/*** 用户信息持久化类* @author pan_junbiao**/
public class User implements Serializable
{private int id; //用户IDprivate String userName; //用户姓名private String blogUrl; //博客地址private String remark; //备注private Date createTime; //创建时间//省略getter与setter方法...
}
package com.pjb.mybatis.po;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;/*** 订单信息持久化类* @author pan_junbiao**/
public class Order implements Serializable
{public int id; //订单IDpublic String orderNo; //订单单号public int productCount; //商品数量public BigDecimal priceTotal; //商品总价public Date createTime; //下单时间public User userInfo; //用户信息//省略getter与setter方法...
}

1.1 association配置方式一

使用SQL关联语句,获取订单信息,同时关联获取用户信息。

(1)创建OrderMapper.xml映射文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test"><resultMap id="orderResultMap" type="com.pjb.mybatis.po.Order"><id property="id" column="order_id"/><result property="orderNo" column="order_no"/><result property="productCount" column="product_count"/><result property="priceTotal" column="price_total"/><result property="createTime" column="order_create_time"/><association property="userInfo" javaType="com.pjb.mybatis.po.User"><id property="id" column="user_id"/><result property="userName" column="user_name"/><result property="blogUrl" column="blog_url"/><result property="remark" column="remark"/><result property="createTime" column="user_create_time"/></association></resultMap><!-- 根据订单ID,获取订单信息 --><select id="getOrderById" parameterType="int" resultMap="orderResultMap">SELECT o.id AS order_id,o.order_no,o.product_count,o.price_total,o.create_time AS order_create_time,u.id AS user_id,u.user_name,u.blog_url,u.remark,u.create_time AS user_create_timeFROM tb_order oLEFT JOIN tb_user u ON o.user_id = u.idWHERE o.id = #{id}</select>
</mapper>

(2)编写执行方法。

/*** 根据订单ID,获取订单信息与关联用户信息* @author pan_junbiao*/
@Test
public void getOrderById()
{DataConnection dataConnection = new DataConnection();SqlSession sqlSession = dataConnection.getSqlSession();Order order = sqlSession.selectOne("test.getOrderById", 1);if (order != null){System.out.println("---------------1、订单信息---------------");System.out.println("订单编号:" + order.getId());System.out.println("订单单号:" + order.getOrderNo());System.out.println("商品数量:" + order.getProductCount());System.out.println("商品总价:" + order.getPriceTotal());System.out.println("下单时间:" + order.getCreateTime());//获取关联的用户信息User user = order.getUserInfo();System.out.println("---------------2、用户信息---------------");System.out.println("用户编号:" + order.getId());System.out.println("用户姓名:" + user.getUserName());System.out.println("博客地址:" + user.getBlogUrl());System.out.println("备注信息:" + user.getRemark());System.out.println("注册时间:" + user.getCreateTime());}sqlSession.close();
}

执行结果:

最终通过resultMap拿到的查询结果,是一个包含user对象信息的Order包装类。

1.2 association配置方式二

当然,如果之前已经定义好了User类对应的resultMap,那么可以在查询结果集配置中引用外部的resultMap来使用,配置方式也使用“association”标签,只不过多设置一个resultMap的属性指向外部的resultMap标签的id。

<resultMap id="orderResultMap" type="com.pjb.mybatis.po.Order"><id property="id" column="order_id"/><result property="orderNo" column="order_no"/><result property="productCount" column="product_count"/><result property="priceTotal" column="price_total"/><result property="createTime" column="order_create_time"/><association property="userInfo" resultMap="userResultMap"/>
</resultMap><resultMap id="userResultMap" type="com.pjb.mybatis.po.User"><id property="id" column="user_id"/><result property="userName" column="user_name"/><result property="blogUrl" column="blog_url"/><result property="remark" column="remark"/><result property="createTime" column="user_create_time"/>
</resultMap><!-- 根据订单ID,获取订单信息 -->
<select id="getOrderById" parameterType="int" resultMap="orderResultMap">SELECT o.id AS order_id,o.order_no,o.product_count,o.price_total,o.create_time AS order_create_time,u.id AS user_id,u.user_name,u.blog_url,u.remark,u.create_time AS user_create_timeFROM tb_order oLEFT JOIN tb_user u ON o.user_id = u.idWHERE o.id = #{id}
</select>

1.3 association配置方式三

如果不使用表的关联关系,而是通过两个SQL查询语句来分别获取订单信息、用户信息。

首先建议开启延迟加载,在MyBatis的全局配置文件SqlMapConfig.xml(mybatis-config.xml)中的<settings>标签中添加“开启延迟加载”配置信息:

<!-- 开启延迟加载开关 -->
<setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载(即按需加载),默认值就是false -->
<setting name="aggressiveLazyLoading" value="false"/>

修改获取订单信息的配置信息,如下:

<resultMap id="orderResultMap" type="com.pjb.mybatis.po.Order"><id property="id" column="id"/><result property="orderNo" column="order_no"/><result property="productCount" column="product_count"/><result property="priceTotal" column="price_total"/><result property="createTime" column="create_time"/><association property="userInfo" select="getUserById" column="user_id"/>
</resultMap><resultMap id="userResultMap" type="com.pjb.mybatis.po.User"><id property="id" column="id"/><result property="userName" column="user_name"/><result property="blogUrl" column="blog_url"/><result property="remark" column="remark"/><result property="createTime" column="create_time"/>
</resultMap><!-- 根据订单ID,获取订单信息 -->
<select id="getOrderById" parameterType="int" resultMap="orderResultMap">SELECT * FROM tb_order WHERE id = #{id}
</select><!-- 根据用户编号,获取用户实体 -->
<select id="getUserById" parameterType="int" resultMap="userResultMap">SELECT * FROM tb_user WHERE id = #{id}
</select>

注意:在上述配置中,association标签中不要在写resultMap属性了,否则会报错!

执行结果:

2、collection属性(集合的嵌套结果)

第二个属性是“集合的嵌套结果”,该属性的标签名称为“collection”。在一些查询结果包装类中,包含一些List集合属性,使用collection标签可以声明该List集合中属性的类型,便于MyBatis对包装类中的集合类型属性进行映射。

【示例】获取订单信息,同时获取该订单关联的商品列表。

(1)在数据库中创建订单商品信息表(tb_order_product),并添加数据。

-- 创建“订单商品信息”数据表
CREATE TABLE IF NOT EXISTS tb_order_product
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '订单商品编号',order_no VARCHAR(50) NOT NULL COMMENT '订单单号',product_id INT DEFAULT '0' COMMENT '商品ID',product_name VARCHAR(50) NOT NULL COMMENT '商品名称',classify_no VARCHAR(50) NOT NULL COMMENT '分类编号',classify_name VARCHAR(50) NOT NULL COMMENT '分类名称',product_count INT DEFAULT '0' COMMENT '商品数量',price DECIMAL(9,2) DEFAULT '0' COMMENT '商品单价'
) COMMENT = '订单商品信息表';-- 添加数据
INSERT INTO tb_order_product(order_no,product_id,product_name,classify_no,classify_name,product_count,price) VALUE('T20191209001',1,'华为手机','1001','手机',2,1599);
INSERT INTO tb_order_product(order_no,product_id,product_name,classify_no,classify_name,product_count,price) VALUE('T20191209001',2,'联想电脑','1002','电脑',3,3699);

(2)创建订单商品信息持久化类(OrderProduct.java)和订单信息持久化类(Order.java)。

package com.pjb.mybatis.po;import java.io.Serializable;
import java.math.BigDecimal;/*** 订单商品信息持久化类* @author pan_junbiao**/
public class OrderProduct implements Serializable
{public int id; //订单商品编号public String orderNo; //订单单号public int productId; //商品IDpublic String productName; //商品名称public String classifyNo; //分类编号public String classifyName; //分类名称public int productCount; //商品数量public BigDecimal price; //商品单价//省略getter与setter方法...
}
package com.pjb.mybatis.po;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;/*** 订单信息持久化类* @author pan_junbiao**/
public class Order implements Serializable
{public int id; //订单IDpublic String orderNo; //订单单号public int productCount; //商品数量public BigDecimal priceTotal; //商品总价public Date createTime; //下单时间public List<OrderProduct> orderProductList; //订单商品列表//省略getter与setter方法...
}

(3)编写OrderMapper.xml配置文件。

<resultMap id="orderResultMap" type="com.pjb.mybatis.po.Order"><id property="id" column="id"/><result property="orderNo" column="order_no"/><result property="productCount" column="product_count"/><result property="priceTotal" column="price_total"/><result property="createTime" column="create_time"/><collection property="orderProductList" column="order_no" select="getOrderProductList" ofType="com.pjb.mybatis.po.OrderProduct"/>
</resultMap><!-- 根据订单ID,获取订单信息 -->
<select id="getOrderById" parameterType="int" resultMap="orderResultMap">SELECT * FROM tb_order WHERE id = #{id}
</select><!-- 根据订单编号,获取订单关联商品列表 -->
<select id="getOrderProductList" parameterType="string" resultType="com.pjb.mybatis.po.OrderProduct">SELECT * FROM tb_order_product WHERE order_no = #{orderNo}
</select>

(4)编写执行方法。

/*** 根据订单ID,获取订单信息与关联商品信息* @author pan_junbiao*/
@Test
public void getOrderById()
{DataConnection dataConnection = new DataConnection();SqlSession sqlSession = dataConnection.getSqlSession();Order order = sqlSession.selectOne("test.getOrderById", 1);if (order != null){System.out.println("---------------1、订单信息---------------");System.out.println("订单编号:" + order.getId());System.out.println("订单单号:" + order.getOrderNo());System.out.println("商品数量:" + order.getProductCount());System.out.println("商品总价:" + order.getPriceTotal());System.out.println("下单时间:" + order.getCreateTime());//获取关联的订单商品列表List<OrderProduct> orderProductList = order.getOrderProductList();System.out.println("---------------2、订单商品列表---------------");for (OrderProduct product :orderProductList){System.out.println("商品编号:" + product.getProductId());System.out.println("商品名称:" + product.getProductName());System.out.println("分类编号:" + product.getClassifyNo());System.out.println("分类名称:" + product.getClassifyName());System.out.println("商品数量:" + product.getProductCount());System.out.println("商品单价:" + product.getPrice());System.out.println("------------------------------");}}sqlSession.close();
}

执行结果:

通过配置“集合的嵌套结果”,就可以将查询结果中的包装类的集合类型的属性嵌套到结果集中。当然同“association”标签一样,“collection”标签也可以引入外部的resultMap配置。如下:

<resultMap id="orderResultMap" type="com.pjb.mybatis.po.Order"><id property="id" column="id"/><result property="orderNo" column="order_no"/><result property="productCount" column="product_count"/><result property="priceTotal" column="price_total"/><result property="createTime" column="create_time"/><collection property="orderProductList" column="order_no" select="getOrderProductList"/>
</resultMap><resultMap id="orderProductResultMap" type="com.pjb.mybatis.po.OrderProduct"><id property="id" column="id"/><result property="orderNo" column="order_no"/><result property="productId" column="product_id"/><result property="productName" column="product_name"/><result property="classifyNo" column="classify_no"/><result property="classifyName" column="classify_name"/><result property="productCount" column="product_count"/><result property="price" column="price"/>
</resultMap><!-- 根据订单ID,获取订单信息 -->
<select id="getOrderById" parameterType="int" resultMap="orderResultMap">SELECT * FROM tb_order WHERE id = #{id}
</select><!-- 根据订单编号,获取订单关联商品列表 -->
<select id="getOrderProductList" parameterType="string" resultMap="orderProductResultMap">SELECT * FROM tb_order_product WHERE order_no = #{orderNo}
</select>

3、discriminator(鉴别器)

在MyBatis的SQL查询结果集中,有时候需要根据某个字段的值,来决定关联哪种结果集,此时就是需要使用“discriminator(鉴别器)”来实现。

【示例】获取商品信息,并根据不同的商品分类获取对应的附加信息。

(1)在数据库中创建手机信息表(tb_mobile_info)和电脑信息表(tb_computer_info),并添加数据。

-- 创建“手机信息”数据表
CREATE TABLE IF NOT EXISTS tb_mobile_info
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',product_id INT DEFAULT '0' COMMENT '商品ID',camera_pixels VARCHAR(50) COMMENT '相机像素',battery_capacity VARCHAR(50) COMMENT '电池容量'
) COMMENT = '手机信息表';-- 添加数据
INSERT INTO tb_mobile_info(product_id,camera_pixels,battery_capacity) VALUE(1,'4800万像素','4000mAh');
-- 创建“电脑信息”数据表
CREATE TABLE IF NOT EXISTS tb_computer_info
( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',product_id INT DEFAULT '0' COMMENT '商品ID',processor_model VARCHAR(50) COMMENT '处理器',graphics_card VARCHAR(50) COMMENT '显卡'
) COMMENT = '电脑信息表';-- 添加数据
INSERT INTO tb_computer_info(product_id,processor_model,graphics_card) VALUE(2,'Intel i7','RTX2060');

(2)创建商品信息久化类(Product.java)。

package com.pjb.mybatis.po;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;/*** 商品信息久化类* @author pan_junbiao**/
public class Product implements Serializable
{public int productId; //商品编号public String productName; //商品名称public String classifyNo; //分类编号public String classifyName; //分类名称public BigDecimal price; //商品单价public HashMap additiveAttributes; //商品附加属性//省略getter与setter方法...
}

(3)编写ProductMapper.xml配置文件。

<!-- 商品信息resultMap -->
<resultMap id="productResultMap" type="com.pjb.mybatis.po.Product"><id property="productId" column="product_id"/><result property="productName" column="product_name"/><result property="classifyNo" column="classify_no"/><result property="classifyName" column="classify_name"/><result property="price" column="price"/><association property="additiveAttributes" javaType="java.util.HashMap"><discriminator javaType="string" column="classify_no"><!-- 1001 手机 --><case value="1001" resultMap="mobileResultMap"/><!-- 1002 电脑 --><case value="1002" resultMap="computerResultMap"/></discriminator>
</association>
</resultMap><!-- 手机附加信息resultMap -->
<resultMap id="mobileResultMap" type="java.util.HashMap"><!-- 相机像素 --><result property="cameraPixels" column="camera_pixels"/><!-- 电池容量 --><result property="batteryCapacity" column="battery_capacity"/>
</resultMap><!-- 电脑附加信息resultMap -->
<resultMap id="computerResultMap" type="java.util.HashMap"><!-- 处理器 --><result property="processorModel" column="processor_model"/><!-- 显卡 --><result property="graphicsCard" column="graphics_card"/>
</resultMap><!-- 获取手机商品信息 -->
<select id="getMobileProductInfo" parameterType="int" resultMap="productResultMap">SELECT p.product_id,p.product_name,p.classify_no,p.classify_name,p.price,m.camera_pixels,m.battery_capacityFROM tb_order_product pLEFT JOIN tb_mobile_info m ON p.product_id = m.product_idWHERE p.product_id = #{id}
</select><!-- 获取电脑商品信息 -->
<select id="getComputerProductInfo" parameterType="int" resultMap="productResultMap">SELECT p.product_id,p.product_name,p.classify_no,p.classify_name,p.price,c.processor_model,c.graphics_cardFROM tb_order_product pLEFT JOIN tb_computer_info c ON p.product_id = c.product_idWHERE p.product_id = #{id}
</select>

(4)编写执行方法,获取手机商品信息。

/*** 获取手机商品信息* @author pan_junbiao*/
@Test
public void getMobileProductInfo()
{DataConnection dataConnection = new DataConnection();SqlSession sqlSession = dataConnection.getSqlSession();Product product = sqlSession.selectOne("test.getMobileProductInfo", 1);if (product != null){System.out.println("---------------1、商品信息---------------");System.out.println("商品编号:" + product.getProductId());System.out.println("商品名称:" + product.getProductName());System.out.println("分类编号:" + product.getClassifyNo());System.out.println("分类名称:" + product.getClassifyName());System.out.println("商品单价:" + product.getPrice());//获取商品附加信息System.out.println("---------------2、商品附加信息---------------");HashMap additiveAttributes = product.getAdditiveAttributes();if(additiveAttributes!=null){System.out.println("相机像素:" + additiveAttributes.get("cameraPixels"));System.out.println("电池容量:" + additiveAttributes.get("batteryCapacity"));}}sqlSession.close();
}

执行结果:

(5)编写执行方法,获取电脑商品信息。

/*** 获取电脑商品信息* @author pan_junbiao*/
@Test
public void getComputerProductInfo()
{DataConnection dataConnection = new DataConnection();SqlSession sqlSession = dataConnection.getSqlSession();Product product = sqlSession.selectOne("test.getComputerProductInfo", 2);if (product != null){System.out.println("---------------1、商品信息---------------");System.out.println("商品编号:" + product.getProductId());System.out.println("商品名称:" + product.getProductName());System.out.println("分类编号:" + product.getClassifyNo());System.out.println("分类名称:" + product.getClassifyName());System.out.println("商品单价:" + product.getPrice());//获取商品附加信息System.out.println("---------------2、商品附加信息---------------");HashMap additiveAttributes = product.getAdditiveAttributes();if(additiveAttributes!=null){System.out.println("处理器:" + additiveAttributes.get("processorModel"));System.out.println("显卡:" + additiveAttributes.get("graphicsCard"));}}sqlSession.close();
}

执行结果:

从执行结果中可以看到,当 classify_no(分类编号)字段的结果为1001时,加载的是手机附加信息resultMap,而当字段的结果为1002时,加载的是电脑附加信息resultMap。这样可以根据不同的情况,映射不同的结果集。

MyBatis关联嵌套映射(association、collection、discriminator)相关推荐

  1. 元素类型为 “resultMap” 的内容必须匹配 “(constructor?,id*,result*,association*,collection*,discriminator?)”

    错误 原配置如下: <resultMap id="xxxDetail" type="xxx" extends="xxxResult"& ...

  2. mybatis多对一映射association详解

    简单映射(一对一) 多对一映射 方式1:按照查询嵌套处理 方式2:按照结果嵌套处理 简单映射(一对一) mybatis结果集映射ResultMap 多对一映射 我们有2个类,一个班级类ClassRoo ...

  3. Mybatis 高级结果映射 ResultMap Association Collection

    来源:http://www.verydemo.com/demo_c152_i1880.html MyBatis的创建基于这样一个思想:数据库并不是您想怎样就怎样的.虽然我们希望所有的数据库遵守第三范式 ...

  4. 三分钟带你了解mybatis关联映射(案例分析一对一,多对多)

    ------------------------------------------------原创不易,如若喜欢,请点一点赞吧!----------------------------------- ...

  5. MyBatis关联映射例题

    在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍.模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题 ...

  6. Mybatis关联映射;Mybatis注解

    Mybatis关联映射 Mybatis关联映射的用途: 在实际的开发过程中,对于数据库的操作除了单表外往往会涉及到多张表,这些操作在面向对象中就涉及到了对象与对象之间的关联关系.针对多表之间的操作,M ...

  7. mybatis collection标签_一对多的关系,在MyBatis中如何映射?

    # 使用collection标签 需求:根据用户id查询用户信息的同时获取用户拥有的角色,一个用户可以拥有1个或多个角色. 一般情况下,不建议直接修改数据库表对应的实体类. 所以这里我们延用之前博客中 ...

  8. Mybatis源码阅读(三):结果集映射3.2 —— 嵌套映射

    *************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如 ...

  9. MyBatis关联映射:一对一、一对多

    一.一对一 场景:生活中每一个人都有一个身份证,这是最简单的一对一的关系. (1)用户表 (2)身份证表 (3)用户实体对象,com.xuliugen.mybatis.demo.bean.User ( ...

最新文章

  1. 计算文本文件中各个词(中英文)出现的频率
  2. MySQL WHERE:条件查询
  3. MFC中动态创建控件以及事件响应实现方法
  4. Django model 字段类型及选项解析(一)
  5. String类以及String与基本数据类型/char[]/byte[]之间的转换
  6. 【转】android gravity属性 和 weight属性
  7. python3闭包通俗解释_python通俗解说闭包
  8. 计算机中间层怎么解决,电脑中间层服务器地址怎么看
  9. mysql新建数据库并执行sql文件
  10. 操作系统理论:信号量机制与共享资源的并发访问问题
  11. android 焦点的作用,详细介绍Android中的视图焦点Focus的使用
  12. HDU - 6070
  13. 2017_Generating high-quality crowd density maps using contextual pyramid cnns
  14. C++第一话---->初识C++及命名空间
  15. Docker容器技术与应用(项目2 Docker容器安装和使用)
  16. Elasticsearch7.x索引index的备份和恢复,index索引误删恢复
  17. C++爱心代码(红色)
  18. Mybatis——mapper.xml中常用的SQL相关标签简介
  19. 手机长按android版本,微信长按这个功能,可以触发高级操作,只有安卓手机才有...
  20. 【QA】VMware Workstation 不可恢复错误: (vmx)解决方案

热门文章

  1. java opencv磨皮算法_美肤磨皮算法OpenCV3实现
  2. 你如何破解后安装PS cs6
  3. (无Xcode)Mac OS X中解决 make,gcc等命令找不到
  4. 企业数字化转型的步骤是什么?
  5. 如何实现一个转动的太极图
  6. 【综合】hosts文件位置
  7. 详解AES对称加密(python实现文件加密)
  8. 动态爱心和3D旋转烟花代码
  9. 客户关系维护注意事项 如何维护客户关系
  10. 17.Rust中函数式语言功能:迭代器与闭包