菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
262
0

一对多

原创
05/13 14:22
阅读数 44205

讲述的是一对多的查询。(用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集合属性中。

发表评论

0/200
262 点赞
0 评论
收藏
为你推荐 换一批