首页 > 代码库 > MyBatis应用开发(13)映射之一对一关联
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的导航。
MyBatis应用开发(13)映射之一对一关联