mybatis中一对一关系association标签的使用

目录
  • 一对一关系association标签使用
    • 1、嵌套的resultMap
    • 2、嵌套的select语句
  • association标签三种用法
    • association的用法一
    • association的用法二
    • association的用法三

一对一关系association标签使用

association字面翻译为联合之意,Java项目开发中常遇到一对一关系的结果,例如,一个商品对应一个生产商,在查询结果中如果某两个对象是一对一关系一般使用association标签,用法有两种:

1、嵌套的resultMap

一次性查询出所有结果的相关字段,结果把所有字段映射到不同的对象的类变量中

<resultMap id="map01" type="Model01">
    <id column="..." property="..."/>
    <result column="..." property="...">
    ...
    <!--Model01和Model02为一对一关系-->
    <association property="数据类型为Model02在Model01的类变量名称" javaType="Model02" resultMap="map02"/>
</resultMap>
 
<resultMap id="map02" type="Model02">
    <id column="..." property="..."/>
    <result column="..." property="...">
    ...
</resultMap>
 
<select id="select01" resultMap="map01">
    select ...最多查询出Model01,Model02所对应的所有字段 
    from table1(,table2可能需要) 
    where ... 
    order by ...
</select>

说明:

分别有两个类Model01,Model02,但Model01中有一个类变量的数据类型为Model02 ,id为 select01 的SQL语句所查询的结果映射到 map01 的对应 Model01 对象的各类变量中,因 map01 中使用 association 标签,其 property属性 指定 Model01 中的数据类型为 Model02 的类变量,JavaType属性指定该类变量的数据类型,即Model02,resultMap属性指定对应的结果映射为 map02,map02中列出了相应的表子段和类变量的映射关系,所以一次查出所有需要的字段,只是按不同形式映射到相应各个类的类变量中

2、嵌套的select语句

这种方式实为嵌套一个子查询语句查出关联的实体数据(会产生N+1问题,在多次循环中不好,建议在java层面进行业务分离)

例子如下:

<resultMap id="map03" type="Model03">
    <id column="..." property="..."/>
    <result column="..." property="...">
    ...
    <association property="数据类型为Model04在Model03的类变量名称" javaType="Model04" column="对应map03查询结果的某字段,并且该字段正是子查询select04对应需要的参数值" select="X命名空间.select04"/>
</resultMap>
 
<resultMap id="map04" type="Model04">
    <id column="..." property="..."/>
    <result column="..." property="...">
    ...
</resultMap>
 
<select id="select03" parameterType="Java某数据类型" resultMap="map03">
    select ...最多查询出Model03所对应的所有(不含Model04对应的字段)字段 
    from table1 
    where ... 
    order by ...
</select>
 
<select id="select04" parameterType="Java某数据类型" resultMap="map04">
    select ...最多查询出Model04所对应的所有字段 
    from table2 
    where ... 
    order by ...
</select>

说明:

分别有两个类 Model03,Model04,但Model03中有一个类变量的数据类型为Model04 ,id 为 select03 的SQL语句所查询的结果映射到 map03 的对应 Model03 对象的各类变量中,因 map03 中使用 association 标签,其 property属性 指定 Model03 中的数据类型为 Model04 的类变量,column属性为 map03 中的某字段,该字段值正是子查询select04所需的参数,select属性为指定需要的子查询,即ID为select04的子查询,map04中列出本查询结果相应的表子段和类变量的映射关系,所以首先查出父对象所有需要的所有字段,完成映射,同时使用嵌套的子查询查出所需的字段并映射到相应的类,再把该类付给父级对象对应的变量

association标签三种用法

`father`表

CREATE TABLE `father` (
  `ID` int(11) NOT NULL,
  `NAME` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
INSERT INTO `father` VALUES ('1', '李靖');
INSERT INTO `father` VALUES ('2', '康熙');

`son`表

CREATE TABLE `son` (
  `ID` int(11) NOT NULL,
  `FATHER_ID` int(11) DEFAULT NULL,
  `NAME` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
INSERT INTO `son` VALUES ('1', '2', '雍正');
INSERT INTO `son` VALUES ('2', '1', '哪吒');

Father.java

public class Father {
    private Integer id; 
    private String name; 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }
}

Son.java

public class Son {
    private Integer id; 
    private Father father; 
    private String name; 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public Father getFather() {
        return father;
    }
 
    public void setFather(Father father) {
        this.father = father;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }
}

FatherMapper.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.ksy.kuaishiyan.mapper.FatherMapper" >
  
  <resultMap id="BaseResultMap" type="com.ksy.kuaishiyan.entity.Father" >
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
  </resultMap>
  
  <sql id="Base_Column_List" >
    ID, NAME
  </sql>
  
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from father
    where ID = #{id,jdbcType=INTEGER}
  </select>
  
</mapper>

SonMapper.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.ksy.kuaishiyan.mapper.SonMapper" >
 
  <resultMap id="BaseResultMap" type="com.ksy.kuaishiyan.entity.Son" >
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="FATHER_ID" property="fatherId" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
  </resultMap>
  
  <sql id="Base_Column_List" >
    ID, FATHER_ID, NAME
  </sql>
  
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from son
    where ID = #{id,jdbcType=INTEGER}
  </select>
 
</mapper>

association的用法一

直接在SonMapper.xml中的association标签里写对应的列名, 且列明需要写别名, 例如: father.ID AS F_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.ksy.kuaishiyan.mapper.SonMapper">
 
  <resultMap id="BaseResultMap" type="com.ksy.kuaishiyan.entity.Son">
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
    
    <association property="father" javaType="com.ksy.kuaishiyan.entity.Father"> 
      <id column="F_ID" property="id" jdbcType="INTEGER" />
        <result column="F_NAME" property="name" jdbcType="VARCHAR" />
    </association>
  </resultMap>
 
  <sql id="Base_Column_List">
    son.ID, son.NAME, father.ID AS F_ID, father.NAME AS F_NAME
  </sql>
 
  <select id="selectByPrimaryKey" resultMap="BaseResultMap"
    parameterType="java.lang.Integer">
    select
    <include refid="Base_Column_List" />
    from son, father
    where son.FATHER_ID=father.ID AND son.ID = #{id,jdbcType=INTEGER}
  </select>
 
</mapper>

调用selectByPrimaryKey传入id=2, 查询结果如下

{
    "id": 2,
    "father": {
        "id": 1,
        "name": "李靖"
    },
    "name": "哪吒"
}

association的用法二

association传入一个ResultMap, 改写SonMapper.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.ksy.kuaishiyan.mapper.SonMapper">
 
  <resultMap id="BaseResultMap" type="com.ksy.kuaishiyan.entity.Son">
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
    
    <association property="father" javaType="com.ksy.kuaishiyan.entity.Father" resultMap="com.ksy.kuaishiyan.mapper.FatherMapper.BaseResultMap"></association>
  </resultMap>
 
  <sql id="Base_Column_List">
    son.ID, son.NAME, father.ID AS F_ID, father.NAME AS F_NAME
  </sql>
 
  <select id="selectByPrimaryKey" resultMap="BaseResultMap"
    parameterType="java.lang.Integer">
    select
    <include refid="Base_Column_List" />
    from son, father
    where son.FATHER_ID=father.ID AND son.ID = #{id,jdbcType=INTEGER}
  </select>
 
</mapper>

association 标签中resultMap属性指向FatherMapper.xml中的BaseResultMap, 这种情况下要求father表和son表没有相同名字的字段, 否则会失败. 调用selectByPrimaryKey传入id=2, 查询结果失败如下:

{
    "id": 2,
    "father": {
        "id": 2,
        "name": "哪吒"
    },
    "name": "哪吒"
}

association的用法三

给association传入一个select

<?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.ksy.kuaishiyan.mapper.SonMapper">
 
  <resultMap id="BaseResultMap" type="com.ksy.kuaishiyan.entity.Son">
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
    
    <association column="FATHER_ID" property="father" javaType="com.ksy.kuaishiyan.entity.Father" select="com.ksy.kuaishiyan.mapper.FatherMapper.selectByPrimaryKey"></association>
  </resultMap>
 
  <sql id="Base_Column_List">
    ID, NAME, FATHER_ID
  </sql>
 
  <select id="selectByPrimaryKey" resultMap="BaseResultMap"
    parameterType="java.lang.Integer">
    select
    <include refid="Base_Column_List" />
    from son
    where ID = #{id,jdbcType=INTEGER}
  </select>
 
</mapper>

这种方式相当于将原来的

<result column="FATHER_ID" property="fatherId" jdbcType="INTEGER" /> 

替换成

<association column="FATHER_ID" property="father" javaType="com.ksy.kuaishiyan.entity.Father" select="com.ksy.kuaishiyan.mapper.FatherMapper.selectByPrimaryKey"></association>

改动最小, 需要assonciation标签放到所有result标签之后, select语句还可以延迟加载.

在一个<resultMap/>中,属性出现的先后顺序必须是:constructor-->id --> result--> association-->collection -->discriminator。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解mybatis中association和collection的column传入多个参数问题

    项目中在使用association和collection实现一对一和一对多关系时需要对关系中结果集进行筛选,如果使用懒加载模式,即联合使用select标签时,主sql和关系映射里的sql是分开的,查询参数传递成为问题. mybatis文档: property description column 数据库的列名或者列标签别名.与传递给resultSet.getString(columnName)的参数名称相同.注意: 在处理组合键时,您可以使用column="{prop1=col1,prop2=c

  • mybatis利用association或collection传递多参数子查询

    有时候我们在查询数据库时,需要以查询结果为查询条件进行关联查询. 在mybatis 中通过 association 标签(一对一查询,collection 一对多 查询) 实现延迟加载子查询 <resultMap id="xxxMap" type="xxxx.bean.xxx" extends="zzzzMap"> <association property="destName" javaType="

  • Mybatis中collection和association的使用区别详解

    最近一直把collection和association弄混,所以为了增强自己的记忆,就撸一个关系出来算是总结罢了 1. 关联-association 2. 集合-collection 比如同时有User.java和Card.java两个类 User.java如下: public class User{ private Card card_one; private List<Card> card_many; } 在映射card_one属性时用association标签, 映射card_many时

  • MyBatis映射文件resultMap元素中使用多个association的方法

    现在有一张订单表t_stockorder,其拥有id.code.client_id.merchandise_id.merchandise_number.order_date.operator_id这些字段,其中client_id关联t_client表中code字段,merchandise_id关联t_merchandise表的code字段,operator_id关联t_employee表的code字段. 现在要通过SQL语句将订单表中t_stockorder的数据全部查询出来,SQL语句如下所示

  • mybatis中一对一关系association标签的使用

    目录 一对一关系association标签使用 1.嵌套的resultMap 2.嵌套的select语句 association标签三种用法 association的用法一 association的用法二 association的用法三 一对一关系association标签使用 association字面翻译为联合之意,Java项目开发中常遇到一对一关系的结果,例如,一个商品对应一个生产商,在查询结果中如果某两个对象是一对一关系一般使用association标签,用法有两种: 1.嵌套的resu

  • mybatis中映射文件include标签的应用

    目录 mybatis映射文件include标签应用 1.引用同一个xml中的sql片段 2.引用公用的sql片段 3.对于多个xml文件需要同时引用一段相同的 mybatis sql xml include标签 (代码去重) mybatis映射文件include标签应用 MyBatis中sql标签定义SQL片段,include标签引用,可以复用SQL片段可以使用标签提取出来,在使用的地方使用标签引用即可.sql标签中id属性对应include标签中的refid属性.通过include标签将sql

  • mybatis中sql语句CDATA标签的用法说明

    sql语句CDATA标签的用法 CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data). 在 XML 元素中,"<" 和 "&" 是非法的: "<" 会产生错误,因为解析器会把该字符解释为新元素的开始: "&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始: 在mapper文件中写sql语句时,遇到特殊字符时,如:"<&

  • mybatis中foreach嵌套if标签方式

    目录 mybatis foreach嵌套if标签 xml文件 $和 #的区别 union与union all区别 mybatis if和foreach嵌套 (同一个列,不定个数的查询条件) 有这么一种需求 模板如下图 mybatis foreach嵌套if标签 代码实现: Mapper.java文件 List<Map<String, Object>> getYsxmcodeByYszbh(@Param("qyName") List<String> q

  • mybatis中映射文件(mapper)中的使用规则

    目录 一.增删改 1.增加 2.删除 3.更新 二.传入参数处理 1.单个参数 2.多个参数 3.参数中有Collection(List.Set) 类型或者是数组 4.参数封装成数据模型 5.parameterType 配置 参数 三.查询 1.模糊查询 2.#{}与${}的区别 3.返回属性为resultType 4.返回属性为resultMap 一.增删改 1.增加 <!-- 添加用户--> <insert id="saveUser" parameterType=

  • MyBatis中一对多的xml配置方式(嵌套查询/嵌套结果)

    目录 MyBatis一对多的xml配置 嵌套查询 嵌套结果 一对多关联查询xml配置写法 情景概述 创建表 对应javaPojo 查询客户表client获取客户名下的附件信息 查询客户附件表client_file获取附件所属的客户信息 小结一下 MyBatis一对多的xml配置 用的是window上面的画图板,没法以文字的方式展示出来,见谅 嵌套查询 嵌套结果 一对多关联查询xml配置写法 情景概述 1.有一张客户表 Client ,存储客户信息, 姓名 name ,年龄 age等. 2.有一张

  • Mybatis中使用in()查询的方式详解

    目录 1 使用数组方式 2 使用List集合的方式 3 第三种我们使用Mybatis-plus框架的条件构造器来进行查询 附:Mybatis-plus的条件构造器详细使用教程 总结 这篇文章我会演示几种mybatis中使用in查询的方式. 1 数组.字符串 2 集合 3 使用Myabtis-plus框架的条件构造器来实现 我们在mysql中使用in查询的方式是这样的 那在mybatis中我们使用<foreach>标签来实现包含查询 1 使用数组方式 Mapper: Mapper.xml: &l

  • 在Mybatis中association标签多层嵌套的问题

    目录 association标签多层嵌套问题 排查 从代码上看没有什么问题 正常代码如下 association集合嵌套 这个返回集合有什么用呢 association标签多层嵌套问题 mybatis里查询使用嵌套association标签时,发现内层的association查询的结果一直为null 排查 检查sql执行情况,发现有数据返回,排除 检查property的值是否和pojo中的对应,值一致,排除 检查column的值是否和数据库的相对应,相对应,排除 那么应该是mybatis没有把数

随机推荐