MyBatis应用开发(13)映射之一对一关联

1.1.1. 一对一单向关联

resultMap可以定义实体之间的一对一关联关系。本文将介绍如何实现Person和IdCard之间的一对一单向关联关系。假定在业务逻辑上存在这样的约束:IdCard的personid属性应该等于Person的id属性,一个Person唯一对应于一个IdCard。

目标:Person可以通过idCard属性导航到IdCard,而IdCard不能通过person属性导航到Person。

Person类:

/**   

* @Title: Person.java

* @Package com.test.mybatis3.pojo

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月9日 下午3:21:32

* @version V1.0   

*/

package com.test.mybatis3.pojo;

/**

* @ClassName: Person

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月9日 下午3:21:32

*  

*/

public class Person {

//查询结果记录中并无address字段

private  String  address;

private  String id;

private  String name;

private  int    status;

private  IdCard  idCard;

public IdCard getIdCard() {

return idCard;

}

public void setIdCard(IdCard idCard) {

this.idCard = idCard;

}

//用于满足POJO要求的无参数构造函数。

public Person()

{

}

public String getAddress() {

return address;

}

public String getId() {

return id;

}

public String getName() {

return name;

}

public int getStatus() {

return status;

}

public void setAddress(String address) {

this.address = address;

}

public void setId(String id) {

this.id = id;

}

public void setName(String name) {

this.name = name;

}

public void setStatus(int status) {

this.status = status;

}

@Override

public String toString() {

return "Person [id=" + id + ", name=" + name + ", status=" + status + ",address=" + address+"]";

}

}

IdCard类:

/**   

* @Title: IdCard.java

* @Package com.test.mybatis3.pojo

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月16日 下午2:01:50

* @version V1.0   

*/

package com.test.mybatis3.pojo;

/**

* @ClassName: IdCard

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月16日 下午2:01:50

*  

*/

public class IdCard {

private String  cardid;

private String  personid;

private Person  person;

public Person getPerson() {

return person;

}

public void setPerson(Person person) {

this.person = person;

}

public String getCardid() {

return cardid;

}

public void setCardid(String cardid) {

this.cardid = cardid;

}

public String getPersonid() {

return personid;

}

public void setPersonid(String personid) {

this.personid = personid;

}

@Override

public String toString() {

return "IdCard [cardid=" + cardid + ", personid=" + personid + ", person=" + person + "]";

}

}

Mapper配置:

<!-- resultMap:Person和IdCard的一对一关联 -->

<resultMap type="com.test.mybatis3.pojo.Person" id="personAndIdCardResultMap">

<id property="id" column="id" />

<result  property="name" column="name" />

<result  property="status" column="status" />

<!-- Person通过idCard属性导航到IdCard -->

<association property="idCard" javaType="com.test.mybatis3.pojo.IdCard" >

<!-- 此id结点配置IdCard(t_idcard)的主键cardid -->

<id  property="cardid" column="cardid"  />

<result property="personid" column="personid"/>

<!-- 此处并没有定义IdCard如何导航到Person ,因此是单向关联-->

</association>

</resultMap>

<!-- 查找 Person和对应的IdCard-->

<select id="findPersonAndIdCard" resultMap="personAndIdCardResultMap">

select a.* , b.* from t_person a left join t_idcard b on a.id=b.personid

</select>

Mapper接口:

/**

 * 查找Person和对应的IdCard

 * @return

 * @throws Exception

 */

List<Person> findPersonAndIdCard() throws Exception;

单元测试代码:

//打开Session。

session = sessionBuilder.openSession();

//找到MyBatis自动实现的PersonMapper接口的代理对象。

PersonMapper  personMapper = session.getMapper(PersonMapper.class);

List<Person> persons = personMapper.findPersonAndIdCard();

//输出查询结果。

for(Person person : persons){

System.out.println(person);

System.out.println(person.getIdCard());

}

运行结果如下:

0    [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - ==>  Preparing: select a.* , b.* from t_person a left join t_idcard b on a.id=b.personid

46   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - ==> Parameters:

64   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - <==    Columns: id, name, status, personid, cardid

64   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - <==        Row: lisi, li si, 0, lisi, 222222222222222222

66   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - <==        Row: zhangsan, zhang san, 0, zhangsan, 1111111111111111

66   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCard  - <==      Total: 2

Person [id=lisi, name=li si, status=0,address=null]

IdCard [cardid=222222222222222222, personid=lisi, person=null]

Person [id=zhangsan, name=zhang san, status=0,address=null]

IdCard [cardid=1111111111111111, personid=zhangsan, person=null]

由于是单向关联,Person的idCard属性已被赋值,IdCard的对应实例也是MyBatis自动创建的;反过来,IdCard的person属性则没有被赋值。

1.1.2. 一对一双向关联

在Person通过idCard导航到IdCard的基础上,再通过映射建立IdCard到Person的导航,则可以实现双向关联。

Mapper配置:

<!-- resultMap:Person和IdCard的一对一关联:双向关联 -->

<resultMap type="com.test.mybatis3.pojo.Person" id="personAndIdCardBidirectionResultMap">

<id property="id" column="id" />

<result  property="name" column="name" />

<result  property="status" column="status" />

<

<!-- Person通过idCard属性导航到IdCard -->

<association property="idCard" javaType="com.test.mybatis3.pojo.IdCard" >

<!-- 此id结点配置IdCard(t_idcard)的主键cardid -->

<id  property="cardid" column="cardid"  />

<result property="personid" column="personid"/>

<!-- IdCard通过person属性导航到Person ,因此是双向关联-->

<association property="person" javaType="com.test.mybatis3.pojo.Person">

<id property="id" column="personid" />

</association>

</association>

</resultMap>

<!-- 查找 Person和对应的IdCard:双向关联-->

<select id="findPersonAndIdCardBidirection" resultMap="personAndIdCardBidirectionResultMap">

select a.* , b.* from t_person a left join t_idcard b on a.id=b.personid

</select>

Mapper接口:

/**

 * 查找Person和对应的IdCard:双向关联。

 * @return

 * @throws Exception

 */

List<Person> findPersonAndIdCardBidirection() throws Exception;

单元测试代码:

//打开Session。

session = sessionBuilder.openSession();

//找到MyBatis自动实现的PersonMapper接口的代理对象。

PersonMapper  personMapper = session.getMapper(PersonMapper.class);

List<Person> persons = personMapper.findPersonAndIdCardBidirection();

//输出查询结果。

for(Person person : persons){

System.out.println(person);

System.out.println(person.getIdCard());

//查看person和idCard的person是否同一个对象。

System.out.println(person == person.getIdCard().getPerson());

}

运行结果如下:

0    [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - ==>  Preparing: select a.* , b.* from t_person a left join t_idcard b on a.id=b.personid

54   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - ==> Parameters:

72   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - <==    Columns: id, name, status, personid, cardid

73   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - <==        Row: lisi, li si, 0, lisi, 222222222222222222

75   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - <==        Row: zhangsan, zhang san, 0, zhangsan, 1111111111111111

77   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardBidirection  - <==      Total: 2

Person [id=lisi, name=li si, status=0,address=null]

IdCard [cardid=222222222222222222, personid=lisi, person=Person [id=lisi, name=li si, status=0,address=null]]

false

Person [id=zhangsan, name=zhang san, status=0,address=null]

IdCard [cardid=1111111111111111, personid=zhangsan, person=Person [id=zhangsan, name=zhang san, status=0,address=null]]

false

结果表明:按照这种方式,可以产生双向关联关系映射,但是存在一个不足之处,就是person和其idCard的person不是同一个对象:person == person.getIdCard().getPerson()的结果为false。

表明MyBatis创建了多余的Person对象。可以在Mapper配置中仅仅建立单向关联关系,然后在Service方法中编写代码建立IdCard到Person的导航。

时间: 2025-01-13 09:33:55

MyBatis应用开发(13)映射之一对一关联的相关文章

MyBatis应用开发(14)映射之嵌套查询

1.1.1. 嵌套查询 使用association结点的select属性可以建立嵌套查询.前文介绍的不使用select的方法在主表结果记录集包含N条记录,每个记录对应1条子表记录的情况下,总共执行一条SQL语句就可以满足整个查询操作的要求,而本文介绍的select属性建立嵌套查询的方法,则 需要执行1+N条SQL语句(单向关联),或者1+N*2条语句(双向关联). Mapper配置: <!-- 主表resultMap:Person和IdCard的一对一关联:双向关联,嵌套查询 --> <

MyBatis应用开发(15)映射之一对多关联

1.1.1. 一对多关联 一个Person可以拥有一个或多个Address,而每个Address对应于唯一一个Person,因此Person和Address之间存在一对多的关系.本文介绍使用MyBatis如何进行基于List的一对多映射. Person类: /** * @Title: Person.java * @Package com.test.mybatis3.pojo * @Description: * @author http://www.cnblogs.com/coe2coe/ * @

三、MyBatis系列:Mapper 映射 之 多级关联查询结果映射

现在有这么几张表,员工表(user).订单(orders).订单明细(orderdetails).产品信息(items)它们的物理模型图如下: 希望能查询出某些用户下的订单详细信息,而且希望能一条SQL查出所有相关的数据,并映射到POJO实体中.返回的结果应该包含用户信息.订单及明细.相应产品信息.数据映射为实体结构如下: 1 package cn.xleos.mybatis.po; 2 3 public class User { 4 private int id; 5 private Stri

MyBatis应用开发(10)映射之结果映射resultType

1.1. resultType 1.1.1. 结果为单条记录 查询结果为单条记录时,resultType应该为一个Java Bean类型. select语句的查询结果字段列表可以和resultType指定的Java Bean类型的属性列表不同,字段可以没有对应的属性,属性也可以没有对应的字段,即允许存在多余的字段,或者多余的属性. <!-- findPersonById:根据id查找单个记录. id:SQL语句的ID,应该与PersonMapper接口的findPersonById方法一一对应.

MyBatis应用开发(11)映射之结果映射字段别名和HashMap

1.1.1. 字段别名的特殊功能 通过SQL语句的字段别名功能,可以将记录映射到resultType指定的Java Bean类型的属性的属性上. <!-- 通过定义select语句的字段别名为XXX.YYY的形式,可以将字段值赋值给PersonWrapper类的属性person的属性 --> <select id="findPersonWrapper" parameterType="java.lang.String" resultType=&quo

MyBatis应用开发(12)映射之结果映射resultMap

1.1.1. 使用resultMap映射字段和属性 MyBatis的resultMap可以方便的定义字段和属性之间的映射关系,字段和属性的名称可以相同,也可以不相同. <!-- personResultMap:将t_person的记录的字段映射到SomeBean的属性上 --> <resultMap type="com.test.mybatis3.pojo.SomeBean" id="personResultMap"> <id prop

MyBatis应用开发(8)映射之select语句

1. 映射 1.1. select select语句有以下几种情况: (1)查找单条记录. (2)查找多条记录. 如果直接使用SqlSession接口来获取查询结果,则应使用selectOne()方法来查询单条记录,使用selectList()方法来查询多条记录. 本文采用没有采用这种方式,而是使用Mapper接口的方式来获取查询结果.为了节省篇幅和直奔主题,本文没有定义Service接口及其实现类,而是在单元测试代码中使用Mapper接口调用相应方法. 1.1.1. 查找单条记录 (1)Per

MyBatis应用开发(9)映射之参数绑定parameterType

1.1. parameterType parameterType表示SQL语句中存在占位符,对应于Mapper接口中对应方法的参数. 当SQL语句中只有一个占位符时,parameterType可以是Java基本类型,也可以是Java Bean类型.当存在多个占位符时,parameterType只能是Java Bean类型. 当为Java基本类型时,可以写类型的全限定名,也可以是MyBatis提供的简化的别名. 别名int表示java.lang.Integer. 别名string表示java.la

论坛:一对一关联映射/单向关联/两个类间,可以有两个(多个)关联关系/content为大文本类型/

>>单向:只写一端的映射属性,另一端不写(有一端用不着);双向:两端都写映射属性 >>一对一关联有两类:一类基于主键的(一般不使用),一类基于外键的(重点学习): 外键:是一个普通字段,该字段的值是另一张表的主键.比如,A表中的一个字段,是B表的主键,那他就可以是A表的外键. 外键可以重复, 可以是空值.与主键唯一非空区别: 一对一:即在多的一方,外键上添加<many to one name="" colum="" class=&quo