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

1.1.1. 嵌套查询

使用association结点的select属性可以建立嵌套查询。前文介绍的不使用select的方法在主表结果记录集包含N条记录,每个记录对应1条子表记录的情况下,总共执行一条SQL语句就可以满足整个查询操作的要求,而本文介绍的select属性建立嵌套查询的方法,则

需要执行1+N条SQL语句(单向关联),或者1+N*2条语句(双向关联)。

Mapper配置:

<!-- 主表resultMap:Person和IdCard的一对一关联:双向关联,嵌套查询 -->

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

<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" column="id" select="findIdCardByCardId">

</association>

</resultMap>

<!-- 子表resultMap:IdCard的映射 -->

<resultMap type="com.test.mybatis3.pojo.IdCard" id="idCardResultMap">

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

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

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

<association property="person" column="personid" select="findPersonByPersonId">

</association>

</resultMap>

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

<select id="findPersonAndIdCardEmbeded" resultMap="personAndIdCardEmbeddedResultMap">

select * from t_person

</select>

<!-- 子表:通过personid查找IdCard -->

<select id="findIdCardByCardId" parameterType="string" resultMap="idCardResultMap">

select * from t_idcard where personid=#{personid}

</select>

<!-- 用于IdCard的映射中从personid查找Person -->

<select id="findPersonByPersonId" parameterType="string" resultType="com.test.mybatis3.pojo.Person" >

select * from t_person where id=#{id}

</select>

Mapper接口:

/**

 * 嵌套查询:Person和IdCard.

 * @return

 * @throws Exception

 */

List<Person> findPersonAndIdCardEmbeded() throws Exception;

单元测试代码:

//打开Session。

session = sessionBuilder.openSession();

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

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

//嵌套查询。

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

//输出查询结果。

for(Person person : persons){

System.out.println(person);

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

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

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

}

运行结果如下:

1    [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardEmbeded  - ==>  Preparing: select * from t_person

43   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardEmbeded  - ==> Parameters:

67   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardEmbeded  - <==    Columns: id, name, status

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

70   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - ====>  Preparing: select * from t_idcard where personid=?

70   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - ====> Parameters: lisi(String)

71   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====    Columns: personid, cardid

72   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====        Row: lisi, 222222222222222222

72   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - ======>  Preparing: select * from t_person where id=?

72   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - ======> Parameters: lisi(String)

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

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

74   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - <======      Total: 1

74   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====      Total: 1

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

75   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - ====>  Preparing: select * from t_idcard where personid=?

75   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - ====> Parameters: zhangsan(String)

75   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====    Columns: personid, cardid

77   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====        Row: zhangsan, 1111111111111111

77   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - ======>  Preparing: select * from t_person where id=?

78   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - ======> Parameters: zhangsan(String)

78   [main] TRACE com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - <======    Columns: id, name, status

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

78   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonByPersonId  - <======      Total: 1

79   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findIdCardByCardId  - <====      Total: 1

79   [main] DEBUG com.test.mybatis3.mapper.PersonMapper.findPersonAndIdCardEmbeded  - <==      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

观察运行结果可以发现,在双向关联的情况下,主表2条记录(N=2),总共执行了1+N+N=5条SQL语句。如果换成让MyBatis做单向关联,在Service方法中编写代码实现反向关联,则只需要执行1+N条SQL语句。

时间: 2024-10-14 16:18:34

MyBatis应用开发(14)映射之嵌套查询的相关文章

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应用开发(11)映射之结果映射字段别名和HashMap

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

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

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

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

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

1.1.1. 一对一单向关联 resultMap可以定义实体之间的一对一关联关系.本文将介绍如何实现Person和IdCard之间的一对一单向关联关系.假定在业务逻辑上存在这样的约束:IdCard的personid属性应该等于Person的id属性,一个Person唯一对应于一个IdCard. 目标:Person可以通过idCard属性导航到IdCard,而IdCard不能通过person属性导航到Person. Person类: /** * @Title: Person.java * @Pac

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

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

MyBatis总结之高级映射一对多查询

上一篇博文总结了一下一对一的映射,本文主要总结一下一对多的映射,订单项和订单明细是一对多的关系,所以本文主要来查询订单表,然后关联订单明细表,这样就有一对多的问题出来了. 首先还是先写sql语句,在写sql语句的时候遵循两点: 查询的主表是哪个? 订单表 查询的关联表是哪个? 订单明细表 明确了主表和关联表,下面就可以写sql了,我们在上一节的sql基础上添加订单明细表的关联即可. SELECT orders.*, user.`username`, user.`sex`, user.`addre

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之高级关联和集合映射(二、嵌套查询和嵌套结果小案例)

三张表,通过班级 clsId=3001 查找班级和学生的信息 1. 建表 表结构如下 create table student ( stuId number(4) primary key, stuName varchar2(20) not null, stuSex varchar2(4), stuBirthday date, classId number(4) ); create table classes ( clsId number(4) primary key, clsName varch