一对多
讲述的是一对多的查询。(用resultMap)
给出几张表的内容:
User表:
orderdetail表:
orders表:
items表:
在SQLyog中写一个sql语句 (先验证成功):
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
结果是:
其实我们要做的就是:把上面查出来的那个数据表每个字段映射好!!!
好,现在开始:
先给出需求:
查询订单及订单明细的信息。
我们由前面的文章知道查询订单及订单明细的信息是一对多的关系。
我们还是按照:1.sql 2.pojo映射类3.mapper.xml和mapper.java接口这种顺序。
1.sql语句:
确定主查询表:订单表
确定关联查询表:订单明细表
在一对一查询基础上添加订单明细表关联即可。
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,//别名orderdetail_id
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
这种sql查询出来的结果是:
很明显查询出来的结果是重复的(两个id为3的数据,两个id为4的数据,为什么会出现这样的结果,原因是:
我们知道一张订单表会对应多个订单明细表,这样的话就是说一个用户有一张订单表,那么一张订单表上肯定有很多的订单信息表
)
但是上面的这样结果如果用resultType来做的:使用resultType将上边的 查询结果映射到pojo中,订单信息的就是重复。我们采用的是resultMap.
但是我们的需求是:对orders映射不能出现重复记录。
在orders.java类中添加List<orderDetail> orderDetails属性。
最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderDetails属性中。
映射成的orders记录数为两条(orders信息不重复)
每个orders中的orderDetails属性存储了该 订单所对应的订单明细。
效果如下:
上面图Orders只有两条信息,每个Orders中的各有两条orderDetails信息。这样就刚好一一对应了。一对多——完美!
2.根据上面的思路来创建pojo类:
package cn.itcast.mybatis.po;
import java.util.Date;
import java.util.List;
public class Orders {
private Integer id;
private Integer user_id;
private String number;
private Date createtime;
private String note;
//用户信息,新增了一个User属性,为了保存查询得到的关联的User表的信息(一对一)
private User user;
//订单明细。order关联多个orderdetails,(一对多)
private List<Orderdetail> orderdetails;
public List<Orderdetail> getOrderdetail() {
return orderdetails;
}
public void setOrderdetail(List<Orderdetail> orderdetail) {
this.orderdetails = orderdetail;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
3.创建mapper.xml和mapper.java接口。
OrdersMapperCustom.xml代码如下:
OrdersMapperCustom.xm写法一:
<?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">
<!-- nanmespace:命名空间。 作用就是对sql进行分类话管理,理解Sal分离
注意:使用mapper代理方式,namespace有特殊重要的作用
-->
<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
就是说id要能唯一的标识出数据库中的Order表。
column:订单信息的唯 一标识 列
property:订单信息的唯 一标识 列所映射到Orders中哪个属性
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 这一行的作用是要能唯一的识别出order表的,那么很明显是主键id -->
<id column="id" property="id"/>
<!-- 以下的几行result column就是表中的字段 property就是对应到相应pojo类中的属性-->
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的关联的用户信息 -->
<!-- association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<!-- 下面的代码比较特殊,因为Order表是直接关联到user表,下面这么写的目的是把user表映射到Order类中
<association property="user"这里的user指的是orders类中的user,对应的是cn.itcast.mybatis.po.User
-->
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!--
<id column="user_id" property="id"/>这里的是user_id指的是order表中只有这个属性能表示唯一的user表
-->
<id column="user_id" property="id"/>
<!-- 接下来的result property什么的都是为了把user表中的字段能匹配到
cn.itcast.mybatis.po.User这个类的属性中
-->
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrderAndOrderDetailResultMap">
<!-- 订单和用户的设置 -->
<id column="id" property="id"/>
<!-- 以下的几行result column就是表中的字段 property就是对应到相应pojo类中的属性-->
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的关联的用户信息 -->
<!-- association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<!-- 下面的代码比较特殊,因为Order表是直接关联到user表,下面这么写的目的是把user表映射到Order类中
<association property="user"这里的user指的是orders类中的user属性,对应的是cn.itcast.mybatis.po.User
-->
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!--
<id column="user_id" property="id"/>这里的是user_id指的是order表中只有这个属性能表示唯一的user表
-->
<id column="user_id" property="id"/>
<!-- 接下来的result property什么的都是为了把user表中的字段能匹配到
cn.itcast.mybatis.po.User这个类的属性中
-->
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
<!-- 订单明细信息
一个订单关联查询出了多条明细,要使用collection进行映射
collection:对关联查询到多条记录映射到集合对象中
property:将关联查询到多条记录映射到cn.itcast.mybatis.po.Orders哪个属性
ofType:指定映射到list集合属性中pojo的类型
-->
<!--
其是要理解collection的话对比上面的association,association是一对一的映射,而collection是一对多的映射
<collection property="orderdetails" 这里的orderdetails是Orders中一个属性:private List<Orderdetail> orderdetails;
ofType="cn.itcast.mybatis.po.Orderdetail"这里的
cn.itcast.mybatis.po.Orderdetail是List<Orderdetail>里面的Orderdetail类型。
-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<!-- id:订单明细唯 一标识
property:要将订单明细的唯 一标识 映射到cn.itcast.mybatis.po.Orderdetail的哪个属性
-->
<!-- 这里的<id column="orderdetail_id" property="id"/>
orderdetail_id是要唯一能标识orderdetail表的字段,所以选了orderdetail的主键,为什么是orderdetail_id
而不是id呢,原因是为了避免和orders表的id造成冲突,所以取的别名。property="id"是cn.itcast.mybatis.po.Orderdetail
中的属性
-->
<id column="orderdetail_id" property="id"/>
<!-- 这里的result 中column都是orderdetail表中的字段,property是Orderdetail中的属性,要一一映射过去 -->
<result column="items_id" property="items_id"/>
<result column="items_number" property="items_num"/>
<result column="orders_id" property="orders_id"/>
</collection>
</resultMap>
<select id="findOrdersUser" resultType="cn.itcast.mybatis.po.OrdersCustom">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,
user.`address`
FROM orderS,USER
WHERE ORDERS.`user_id`=USER.`id`
</select>
<select id="findOrdersUseResultMap" resultMap="OrdersUserResultMap">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,
user.`address`
FROM orderS,USER
WHERE ORDERS.`user_id`=USER.`id`
</select>
<select id="findOrdersandOrderDetailResultMap" resultMap="OrderAndOrderDetailResultMap">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,user.`address`,
orderdetail.`id` orderdetail_id ,
orderdetail.`items_id`,
orderdetail.`items_num`
FROM orderS,USER ,orderdetail
WHERE ORDERS.`user_id`=USER.`id`AND orderdetail.`orders_id`=Orders.`id`
</select>
</mapper>
OrdersMapperCustom.xm写法二:
发现上面的写法有点复杂,有些代码重复了,我们可以用extends这种做法来避免写重复代码。
<?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">
<!-- nanmespace:命名空间。 作用就是对sql进行分类话管理,理解Sal分离
注意:使用mapper代理方式,namespace有特殊重要的作用
-->
<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
就是说id要能唯一的标识出数据库中的Order表。
column:订单信息的唯 一标识 列
property:订单信息的唯 一标识 列所映射到Orders中哪个属性
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 这一行的作用是要能唯一的识别出order表的,那么很明显是主键id -->
<id column="id" property="id"/>
<!-- 以下的几行result column就是表中的字段 property就是对应到相应pojo类中的属性-->
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的关联的用户信息 -->
<!-- association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<!-- 下面的代码比较特殊,因为Order表是直接关联到user表,下面这么写的目的是把user表映射到Order类中
<association property="user"这里的user指的是orders类中的user,对应的是cn.itcast.mybatis.po.User
-->
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!--
<id column="user_id" property="id"/>这里的是user_id指的是order表中只有这个属性能表示唯一的user表
-->
<id column="user_id" property="id"/>
<!-- 接下来的result property什么的都是为了把user表中的字段能匹配到
cn.itcast.mybatis.po.User这个类的属性中
-->
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!--
用extends OrdersUserResultMap
的话上面的重复代码就不用谢了
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrderAndOrderDetailResultMap"
extends="OrdersUserResultMap">
<!-- 订单明细信息
一个订单关联查询出了多条明细,要使用collection进行映射
collection:对关联查询到多条记录映射到集合对象中
property:将关联查询到多条记录映射到cn.itcast.mybatis.po.Orders哪个属性
ofType:指定映射到list集合属性中pojo的类型
-->
<!--
其是要理解collection的话对比上面的association,association是一对一的映射,而collection是一对多的映射
<collection property="orderdetails" 这里的orderdetails是Orders中一个属性:private List<Orderdetail> orderdetails;
ofType="cn.itcast.mybatis.po.Orderdetail"这里的
cn.itcast.mybatis.po.Orderdetail是List<Orderdetail>里面的Orderdetail类型。
-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<!-- id:订单明细唯 一标识
property:要将订单明细的唯 一标识 映射到cn.itcast.mybatis.po.Orderdetail的哪个属性
-->
<!-- 这里的<id column="orderdetail_id" property="id"/>
orderdetail_id是要唯一能标识orderdetail表的字段,所以选了orderdetail的主键,为什么是orderdetail_id
而不是id呢,原因是为了避免和orders表的id造成冲突,所以取的别名。property="id"是cn.itcast.mybatis.po.Orderdetail
中的属性
-->
<id column="orderdetail_id" property="id"/>
<!-- 这里的result 中column都是orderdetail表中的字段,property是Orderdetail中的属性,要一一映射过去 -->
<result column="items_id" property="items_id"/>
<result column="items_number" property="items_num"/>
<result column="orders_id" property="orders_id"/>
</collection>
</resultMap>
<select id="findOrdersUser" resultType="cn.itcast.mybatis.po.OrdersCustom">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,
user.`address`
FROM orderS,USER
WHERE ORDERS.`user_id`=USER.`id`
</select>
<select id="findOrdersUseResultMap" resultMap="OrdersUserResultMap">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,
user.`address`
FROM orderS,USER
WHERE ORDERS.`user_id`=USER.`id`
</select>
<select id="findOrdersandOrderDetailResultMap" resultMap="OrderAndOrderDetailResultMap">
SELECT ORDERS.* ,
user.`username`,
user.`sex`,user.`address`,
orderdetail.`id` orderdetail_id ,
orderdetail.`items_id`,
orderdetail.`items_num`
FROM orderS,USER ,orderdetail
WHERE ORDERS.`user_id`=USER.`id`AND orderdetail.`orders_id`=Orders.`id`
</select>
</mapper>
OrdersMapperCustom.java接口如下:
package cn.itcast.mybatis.mapper;
import java.util.List;
import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.OrdersCustom;
public interface OrdersMapperCustom {
//函数的名字OrdersMapperCustom.xml中select中的id名一样
public List<OrdersCustom> findOrdersUser();
public List<Orders> findOrdersUseResultMap();
public List<Orders> findOrdersandOrderDetailResultMap();
}
Junit测试代码:
Mybatis_mappertest.java代码如下:
package cn.itcast.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
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 cn.itcast.mybatis.mapper.OrdersMapperCustom;
import cn.itcast.mybatis.mapper.userMapper;
import cn.itcast.mybatis.po.Orders;
import cn.itcast.mybatis.po.User;
import cn.itcast.mybatis.po.UserCustom;
import cn.itcast.mybatis.po.UserQueryVo;
public class Mybatis_mappertest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setup() throws IOException
{ String resource="SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
//主要是生成SqlsessionFactory。
this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testMaper()
{
SqlSession sqlSession=null;
sqlSession=sqlSessionFactory.openSession();
//生成代理类
OrdersMapperCustom orderMapper=sqlSession.getMapper(OrdersMapperCustom.class);
@SuppressWarnings("unused")
//List<Orders>list=orderMapper.findOrdersUseResultMap();
List<Orders> list=orderMapper.findOrdersandOrderDetailResultMap();
}
}
一对多总结:
mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。


浙公网安备 33010602011771号