MyBatis Select一对多和多对一映射详解

在使用MyBatis3的时候,我们经常需要处理一对多和多对一这种方式,通常情况下我们可以通过代码请求两次数据库将数据获取到JavaBean中;那么,MyBatis3是否支持查询映射呢?答案是肯定的。在MyBatis3中我们可以在<resultMap>使用<collection>实现一对多,<association>实现一对一或多对一映射。

在使用MyBatis3的时候,我们经常需要处理一对多和多对一这种方式,通常情况下我们可以通过代码请求两次数据库将数据获取到JavaBean中;那么,MyBatis3是否支持查询映射呢?答案是肯定的。在MyBatis3中我们可以在使用实现一对多,实现一对一或多对一映射。

我们先看看MyBati3s在DTD中是怎样来定义这两个标签的,如下:

<!ELEMENT resultMap (constructor?,id*,result*,association*,collection*, discriminator?)>
<!ATTLIST resultMap
    id CDATA #REQUIRED
    type CDATA #REQUIRED
    extends CDATA #IMPLIED
    autoMapping (true|false) #IMPLIED>
 
<!-- collection标签 -->
<!ELEMENT collection (constructor?,id*,result*,association*,collection*, discriminator?)>
<!ATTLIST collection
    property CDATA #REQUIRED
    column CDATA #IMPLIED
    javaType CDATA #IMPLIED
    ofType CDATA #IMPLIED
    jdbcType CDATA #IMPLIED
    select CDATA #IMPLIED
    resultMap CDATA #IMPLIED
    typeHandler CDATA #IMPLIED
    notNullColumn CDATA #IMPLIED
    columnPrefix CDATA #IMPLIED
    resultSet CDATA #IMPLIED
    foreignColumn CDATA #IMPLIED
    autoMapping (true|false) #IMPLIED
    fetchType (lazy|eager) #IMPLIED>

<!-- association标签 -->
<!ELEMENT association (constructor?,id*,result*,association*,collection*, discriminator?)>
<!ATTLIST association
    property CDATA #REQUIRED
    column CDATA #IMPLIED
    javaType CDATA #IMPLIED
    jdbcType CDATA #IMPLIED
    select CDATA #IMPLIED
    resultMap CDATA #IMPLIED
    typeHandler CDATA #IMPLIED
    notNullColumn CDATA #IMPLIED
    columnPrefix CDATA #IMPLIED
    resultSet CDATA #IMPLIED
    foreignColumn CDATA #IMPLIED
    autoMapping (true|false) #IMPLIED
    fetchType (lazy|eager) #IMPLIED>

注意:上面两个标签有很多属性,这里就不一一介绍,可以根据属性名称看出属性的作用。

数据库脚本如下:

-- 用户表
CREATE TABLE `t_user` (
    `n_userid`  int(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
    `c_name`  varchar(100) ,
    `c_sex`  varchar(10) ,
    `n_age`  int(11) ,
    `b_face`  blob,
    `n_salary`  double ,
    `d_birthday`  datetime ,
    PRIMARY KEY (`n_userid`)
)
-- 联系方式表
CREATE TABLE `t_contact` (
    `n_id`  int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `n_userid`  int(11) ,
    `c_usage`  varchar(255) ,
    `c_number`  varchar(128) ,
    PRIMARY KEY (`n_id`)
)

注意:上面两张表分表表示用户和联系方式,一个用户可能存在多种联系方式,因此用户和联系方式为一对多的映射关系。

数据表对应的实体Bean:

package mybatis.orm.mode;
// 联系方式
public class ORMContact {
	private int nId;
	private int nUserId;
	private String cUsage;
	private String cNumber;	
	private ORMUser user;
	...
	@Override
	public String toString() {
		return "ORMContact [nId=" + nId + ", nUserId=" + nUserId + ", cUsage="
				+ cUsage + ", cNumber=" + cNumber + ", user=" + user + "]";
	}
}

package mybatis.orm.mode;
import java.sql.Timestamp;
import java.util.List;
// 用户表
public class ORMUser {
	private int nUserId;
	private String cName;
	private String cSex;
	private int nAge;
	private Timestamp dBirthday;
	private List contactList;
	...
	@Override
	public String toString() {
		return "ORMUser [nUserId=" + nUserId + ", cName=" + cName + ", cSex="
				+ cSex + ", nAge=" + nAge + ", dBirthday=" + dBirthday
				+ ", contactList=" + contactList + "]";
	}
}

注意:上面两个JavaBean我重写了toString,方便打印JavaBean的值,由于代码太长,去掉了所有的setter和getter方法,你可以使用eclipse工具自动生成。

下面是在Mapper文件中使用标签来处理一对多和一对一隐射关系,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.orm.mapper.ORMMapper">
	<!-- 一对多映射 -->
	<resultMap id="ormUser" type="mybatis.orm.mode.ORMUser">
		<id column="n_userid" property="nUserId" jdbcType="INTEGER" />
		<result column="c_name" property="cName" jdbcType="VARCHAR" />
		<result column="c_sex" property="cSex" jdbcType="VARCHAR" />
		<result column="n_age" property="nAge" jdbcType="INTEGER" />
		<result column="d_birthday" property="dBirthday" jdbcType="TIMESTAMP" />
		<!-- 映射关联的List,一个用户对多个联系方式,使用List来存放联系方式 -->
		<collection column="n_userid" property="contactList"
			ofType="mybatis.orm.mode.ORMContact">
			<id column="n_id" property="nId" jdbcType="INTEGER" />
			<result column="c_usage" property="cUsage" jdbcType="VARCHAR" />
			<result column="c_number" property="cNumber" jdbcType="VARCHAR" />
		</collection>
	</resultMap>
	<select id="joinSelect01" resultMap="ormUser">
		select a.n_userid, a.c_name, a.c_sex, a.n_age, a.n_salary,
				b.n_id, b.c_usage, b.c_number
		  from t_user a
		  join t_contact b on a.n_userid=b.n_userid 
	</select>
	
	<!-- 对象一对一的关联映射,ORMContact对象中有ORMUser对象 -->
	<resultMap id="ormContact" type="mybatis.orm.mode.ORMContact">
		<id column="n_id" property="nId" jdbcType="INTEGER" />
		<result column="c_usage" property="cUsage" jdbcType="VARCHAR" />
		<result column="c_number" property="cNumber" jdbcType="VARCHAR" />
		<!-- 关联映射,映射一个JavaBean,多个联系对应一个用户,即多对一,也可以处理一对一 -->
		<association column="n_userid" property="user" javaType="mybatis.orm.mode.ORMUser">
			<id column="n_userid" property="nUserId" jdbcType="INTEGER" />
			<result column="c_name" property="cName" jdbcType="VARCHAR" />
			<result column="c_sex" property="cSex" jdbcType="VARCHAR" />
			<result column="n_age" property="nAge" jdbcType="INTEGER" />
			<result column="d_birthday" property="dBirthday" jdbcType="TIMESTAMP" />
		</association>
	</resultMap>
	<select id="joinSelect02" resultMap="ormContact">
		select a.n_id, a.n_userid, a.c_usage, a.c_number,
				b.c_name, b.c_sex, b.n_age, b.n_salary, b.d_birthday
		  from t_contact a
		  join t_user b on a.n_userid=b.n_userid 
	</select>
</mapper>

总结:

1、如果要处理以对多,则使用标签,collection是集合的意思,因为在一对多的JavaBean中使用集合来存放多端的所有对象;

2、如果要处理多对一或者一对一,则使用标签,association是关联的意思,因为在多对一或一对一的JavaBean中存在一端的JavaBean;

点击学习 MyBatis 教程,了解更多的 MyBatis 知识!

不是每一次努力都有收获,但是,每一次收获都必须努力。
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号