简单介绍:
在之前的章节,我们简单介绍了MyBatis中的一对一的关联查询,使用了嵌套查询和嵌套结果集两种方式进行讲解,但是在实际的使用中,我们常用的是嵌套结果集的查询方式,所以在一对多的查询中,我们也只针对嵌套结果集的查询方式进行讲解。嵌套结果集映射的核心思想就是通过一条SQL语句查询两个表,然后把两个表中查询出来的字段自定义映射到两个实体类中,最后实体类再进行嵌套。
如果之前已经熟练掌握或者能理解一对一查询中的各个标签的使用,在一对多的查询中的原理也是基本一样的,只不过是将配置一对一查询中的<association>标签换成了<collection>标签,并且增加了一个新的属性叫做ofType,这个属性的值就是我们List列表中的属性的类,关于这个属性我们会在后面使用的时候进行详细的演示。
我们首先来复习一下一对多的数据表查询结构:
那么,对应到SQL语句中就是下面这样:
查询结果如下:
简单地说,就是一张表中的一列数据可以对应另一张表的多行数据,就像这个查询结果一样,张三的信息可以查询出两条订单信息,但是每一条订单信息的只属于张三一个人。
对应到Java类中的效果如下:
查询出多条信息对应就是B类的集合,而B类的每一条信息只能对应一个A类。
使用方法:
<!-- 配置一对多的查询-->
<select id="one_more_select" resultMap="one_more_mappers" parameterType="int">
select u.id , u.name , u.sex , u.order_id uoid , o.order_id ooid , o.order_information
from user u,orders o
where u.order_id = o.order_id and u.id = #{id}
</select>
<resultMap id="one_more_mappers" type="User">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<collection property="ListOrder" ofType="Orders" javaType="java.util.List">
<result property="order_id" column="ooid"/>
<result property="order_information" column="order_information"/>
</collection>
</resultMap>
在实现一对多的嵌套结果集映射中, 我们需要使用一个新的标签:<collection>,使用这个标签配置一对多的嵌套结果集查询,使用一个特殊的属性,ofType:这个属性的含义是指出我们需要填充进List集合中的反省的类型,也就是B类的类型:
只要掌握了这个标签和属性的使用之后,剩下的就和之前的嵌套结果集查询的写法是一样的了,接下来我们来进行完整的代码演示。
代码实现:
数据库内的数据:
SQL映射文件:
<?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">
<!-- 接口式开发有两个规范: -->
<!--1.接口中方法的名称必须与SQL语句的唯一标识,也就是id的值保持一致,resultType就是接口中返回值的类型,parameterType就是接口中方法的参数的类型-->
<!-- 2.mapper标签的namespace属性必须是接口的全路径,否则在运行的时候会无法找到接口对象的SQL映射文件 -->
<mapper namespace="mappers.one_more_select">
<!-- 根据id查询单条数据-->
<select id="selectOne" resultType="user" parameterType="int">
select *
from user
where id = #{id};
</select>
<!-- 查询所有的数据-->
<select id="selectAll" resultType="user">
select *
from user;
</select>
<!-- 配置一对多的查询-->
<select id="one_more_select" resultMap="one_more_mappers" parameterType="int">
select u.id , u.name , u.sex , u.order_id uoid , o.order_id ooid , o.order_information
from user u,orders o
where u.order_id = o.order_id and u.id = #{id}
</select>
<resultMap id="one_more_mappers" type="User">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<collection property="ListOrder" ofType="Orders" javaType="java.util.List">
<result property="order_id" column="ooid"/>
<result property="order_information" column="order_information"/>
</collection>
</resultMap>
</mapper>
接口文件:
package mappers;
import com.mybatis.POJO.User;
import java.util.List;
public interface one_more_select {
public User selectOne(int i);
public List<User> selectAll();
public List<User> one_more_select(int i);
}
实体类:
package com.mybatis.POJO;
import java.util.List;
public class User{
private int id;
private String name;
private String sex;
private List<Orders> ListOrder;
public User() {
}
public User(int id, String name, String sex, List<Orders> listOrder) {
this.id = id;
this.name = name;
this.sex = sex;
ListOrder = listOrder;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public List<Orders> getListOrder() {
return ListOrder;
}
public void setListOrder(List<Orders> listOrder) {
ListOrder = listOrder;
}
@Override
public String toString() {
return "com.mybatis.POJO.User{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", ListOrder=" + ListOrder +
'}';
}
}
package com.mybatis.POJO;
public class Orders {
private int order_id;
private String order_information;
public Orders() {
}
public Orders(int order_id, String order_information) {
this.order_id = order_id;
this.order_information = order_information;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public String getOrder_information() {
return order_information;
}
public void setOrder_information(String order_information) {
this.order_information = order_information;
}
@Override
public String toString() {
return "orders{" + '\n' +
"order_id=" + order_id +
", order_information='" + order_information + '\'' +
'}'+'\n';
}
}
测试类:
package mappers;
import com.mybatis.POJO.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
public class one_more_selectTest {
SqlSession session = null;
one_more_select mapper = null;
@Before
public void setUp() throws Exception {
InputStream stream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(stream);
session = build.openSession(true);
mapper = session.getMapper(one_more_select.class);
}
@Test
public void testSelectOne() {
User user = mapper.selectOne(1);
System.out.println(user);
}
@Test
public void testSelectAll() {
for (User user : mapper.selectAll()) {
System.out.println(user.toString());
}
}
@Test
public void testOne_more_mappers() {
for (User oneMoreMapper : mapper.one_more_select(2)) {
System.out.println(oneMoreMapper.toString());
}
}
}
注意点:
在这个案例中我们需要注意的是A类和B类的嵌套关系一定要清楚,以及ofTyoe的类型一定是B类的属性值,最后就是在自定义映射规则的时候一定要确定规则的正确,对应好每一个列和属性的映射关系。如果发现自己最后的查询结果和自己预期的不一致,首先去检查映射规则是否配置正确。