MyBatis关联嵌套映射(association、collection、discriminator)简介说明

戚薇 MyBatis 发布时间:2023-05-03 22:31:40 阅读数:7253 1
下文笔者讲述MyBatis关联嵌套映射(association、collection、discriminator)简介,如下所示

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

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('java265','https://www.java265.com/','java爱好者');

-- 创建“订单信息”数据表
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('T20230503001',6,1121,1)

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

package com.java265.mybatis.po; 
import java.io.Serializable;
import java.util.Date;
/**
 * 用户信息持久化类
 * 
 **/
public class User implements Serializable
{
    private int id; //用户ID
    private String userName; //用户姓名
    private String blogUrl; //博客地址
    private String remark; //备注
    private Date createTime; //创建时间
 
    //省略getter与setter方法...
}

package com.java265.mybatis.po;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 订单信息持久化类
 * 
 **/
public class Order implements Serializable
{
    public int id; //订单ID
    public String orderNo; //订单单号
    public int productCount; //商品数量
    public BigDecimal priceTotal; //商品总价
    public Date createTime; //下单时间
    public User userInfo; //用户信息
 
    //省略getter与setter方法...
}

association配置方式一

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

1.创建OrderMapper.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="test">
    <resultMap id="orderResultMap" type="com.java265.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.java265.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_time
        FROM tb_order o
        LEFT JOIN tb_user u ON o.user_id = u.id
        WHERE o.id = #{id}
    </select>
</mapper>

2.编写运行方法
/**
 * 根据订单ID,获取订单信息与关联用户信息
 * 
 */
@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();
}

association配置方式二

 
<resultMap id="orderResultMap" type="com.java265.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.java265.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_time
    FROM tb_order o
    LEFT JOIN tb_user u ON o.user_id = u.id
    WHERE o.id = #{id}
</select>

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.java265.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.java265.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属性,否则会报错!

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('T20230503001',1,'java手机','1001','手机',2,1888);
INSERT INTO tb_order_product
   (order_no,product_id,product_name,classify_no,classify_name,product_count,price) 
    VALUE('T20230503001',2,'java电脑','1002','电脑',3,2888);

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

package com.java265.mybatis.po;
import java.io.Serializable;
import java.math.BigDecimal;
/**
 * 订单商品信息持久化类
 * 
 **/
public class OrderProduct implements Serializable
{
    public int id; //订单商品编号
    public String orderNo; //订单单号
    public int productId; //商品ID
    public String productName; //商品名称
    public String classifyNo; //分类编号
    public String classifyName; //分类名称
    public int productCount; //商品数量
    public BigDecimal price; //商品单价
 
    //省略getter与setter方法...
}

package com.java265.mybatis.po;
 
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
 
/**
 * 订单信息持久化类
 * 
 **/
public class Order implements Serializable
{
    public int id; //订单ID
    public 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.java265.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.java265.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.java265.mybatis.po.OrderProduct">
    SELECT * FROM tb_order_product WHERE order_no = #{orderNo}
</select>

4.编写业务逻辑方法 
/**
 * 根据订单ID,获取订单信息与关联商品信息
 * 
 */
@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.java265.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.java265.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,'3800万像素','3000mAh');

-- 创建“电脑信息”数据表
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 i9','GFX3800');

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

package com.java265.mybatis.po;
 
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
/**
 * 商品信息持久化类
 **/
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.java265.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_capacity
    FROM tb_order_product p
    LEFT JOIN tb_mobile_info m ON p.product_id = m.product_id
    WHERE 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_card
    FROM tb_order_product p
    LEFT JOIN tb_computer_info c ON p.product_id = c.product_id
    WHERE p.product_id = #{id}
</select>

4.编写执行方法
  获取手机商品信息

/**
 * 获取手机商品信息
 */
@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.编写业务逻辑方法,获取电脑商品信息

/**
 * 获取电脑商品信息 
 */
@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();
}
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaFramework/MyBatis/202305/6337.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者