Mybatis 实体之间一对多关联(1 : N)

tech2022-12-05  94

实体之间一对多关联很常见,比如老生常谈的班级与学生,一个班级可以有多个学生,一个学生只能属于一个班级。

文本从字典类型表与字典值表的例子入手,使用 MyBatis 完成一对多的映射。

场景描述


现有字典类型表(dict_type),字典值表(dict_value)。一个字典类型可以有多个值,但一个值只属于一个字典类型。

 

Java 实体类的设计


DictionaryTypeDO,对应着数据库 dict_type 数据表,拥有一个 dictionaryTypeList 属性描述它拥有的字典值:

@Data public class DictionaryTypeDO { private Serializable id; private String type; private String description; private LocalDateTime createTime; private LocalDateTime updateTime; private List<DictionaryValueDO> dictionaryTypeList; }

 

DictionaryValueDO,对应着数据库 dict_value 数据表,拥有一个 dictionaryType 描述它所属的字典类型:

@Data public class DictionaryValueDO { private Serializable id; private String label; private String value; private DictionaryTypeDO dictionaryType; }

 

 

Mapper 接口的设计


两个实体类的接口均只有一个方法叫 selectAll(),文本省略,重点在 Mapper.xml 映射文件。

 

 

 

Mapper.xml 文件


以下是 DictionaryTypeMapper.xml 文件,有几个注意点:

1. 使用了 resultMap 自定义结果映射

2. resultMap 对于 collection 的映射有连接查询、分步查询,从性能考虑使用了连接查询

3. resultMap 映射必须设置 id 元素,

 

<?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.cannedbread.dictionary.mapper.DictionaryTypeMapper"> <resultMap type="com.cannedbread.dictionary.pojo.domain.DictionaryTypeDO" id="doctionaryType"> <id column="t_id" property="id" javaType="java.lang.String"/> <result column="t_type" property="type"/> <result column="t_description" property="description"/> <collection property="dictionaryTypeList" ofType="com.cannedbread.dictionary.pojo.domain.DictionaryValueDO"> <id column="v_id" property="id" javaType="java.lang.String"/> <result column="v_label" property="label"/> <result column="v_value" property="value"/> </collection> </resultMap> <select id="selectAll" resultMap="doctionaryType"> SELECT sdt.id AS 't_id', sdt.type AS 't_type', sdt.description AS 't_description', sdv.id AS 'v_id', sdv.label AS 'v_label', sdv.value AS 'v_value' FROM sys_dict_type sdt LEFT JOIN sys_dict_value sdv ON sdt.id = sdv.dict_type_id </select> </mapper>

DictValueMapper.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.jiangchunbo.app.mapper.DictValueMapper"> <resultMap type="com.jiangchunbo.app.domain.DictValueDO" id="dictValueResultMap"> <id column="id" property="id" /> <result column="label" property="label" /> <result column="value" property="value" /> <result column="create_time" property="createTime" /> <result column="update_time" property="updateTime" /> <result column="is_deleted" property="deleted" /> <association property="dictType" javaType="com.jiangchunbo.app.domain.DictTypeDO" fetchType="eager"> <id column="t.id" property="id" /> <result column="t.type" property="type" /> <result column="t.description" property="description" /> <result column="t.create_time" property="createTime" /> <result column="t.update_time" property="updateTime" /> <result column="t.is_deleted" property="deleted" /> </association> </resultMap> <sql id="dictValueColumns"> v.id , v.dict_type_id , v.label, v.value , v.create_time , v.update_time , v.is_deleted </sql> <sql id="dictTypeColumns"> , t.id AS 't.id' , t.type AS 't.type' , t.description AS 't.description' , t.create_time AS 't.create_time' , t.update_time AS 't.update_time' , t.is_deleted AS 't.is_deleted' </sql> <select id="selectByDictTypeId" resultMap="dictValueResultMap"> SELECT <include refid="dictValueColumns" /> FROM dict_value WHERE dict_type_id = #{dictTypeId} </select> <select id="selectAll" resultMap="dictValueResultMap"> SELECT <include refid="dictValueColumns" /> <include refid="dictTypeColumns" /> FROM dict_value AS v LEFT JOIN dict_type AS t ON t.id = v.dict_type_id </select> </mapper>

 <association> 用于 “1” 这一端,用于描述 “N” 这一端的信息。但与 1 对 1 不同的是,他不使用 select 进行查询(防止无限嵌套),而是直接在语句中进行连接查询。不过注意,如果多表查询有字段名字相同,如 id,需要给予别名,防止无法映射

property:Java 类属性名字

javaType:“1” 这一端关联 Java 类全限定名

 

最新回复(0)