MyBatis关联嵌套映射(association、collection、discriminator)简介说明
下文笔者讲述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(); }
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。