【Mybatis高级映射】一对一映射、一对多映射、多对多映射


前言

       当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射。对于SSM的Mybatis来说,肯定也是差不多的。既然开了头了,我们就也来简单说一些Mybatis的高级映射。当然说到这些东西的时候,最简单也最常用的就是级联查询,所以我们就以几个简单的级联查询为例,分别说一下Mybatis的一对一、一对多、多对多查询。

一、一对一映射

1、需求:

       电商类做买卖,用户提交订单后,某宝根据订单信息和客户的姓名、地址派送,现在查询所有的订单信息,关联查询下但用户信息。

(1)首先确定执行的sql语句为:

SELECT orders.*,user.username,userss.address FROM orders,user WHEREorders.user_id = user.id

resultType方式解决这个问题:

(1)定义po类:

public class OrdersCustom extends Orders {  //OrdersCustom类继承Orders类后OrdersCustom类包括了Orders类的所有字
段,只需要定义用户的信息字段即可。
 
    private String username;// 用户名称
    private String address;// 用户地址
    public String getUsername(){
                return username;
    }
    public String setUsername(String username){
                this.username=username;
    }
     ……
}


(2)Mapper映射文件:

<!-- 查询所有订单信息 -->
    <select id="findOrdersList" resultType="cn.itcast.mybatis.po.OrdersCustom">
    SELECT
    orders.*,
    user.username,
    user.address
    FROM
    orders,    user
    WHERE orders.user_id = user.id
    </select>

(3)定义mapper接口:

public List<OrdersCustom> findOrdersList() throws Exception;

(4)测试:

Public void testfindOrdersList()throws Exception{
       //获取session
       SqlSession session = sqlSessionFactory.openSession();
       //获限mapper接口实例
       UserMapper userMapper = session.getMapper(UserMapper.class);
       //查询订单信息
       List<OrdersCustom> list =userMapper.findOrdersList();
       System.out.println(list);
       //关闭session
       session.close();
    }


使用resultMap解决问题:

(1)定义resultMap:

<!-- 订单信息resultmap___需要关联查询映射的是用户信息,使用association将用户信息映射到订单对象的用户属性中 -->
<resultMap type="cn.itcast.mybatis.po.Orders"id="userordermap">
<!-- 这里的id,是mybatis在进行一对一查询时将user字段映射为user对象时要使用,必须写 -->
<id property="id" column="id"/>
<resultproperty="user_id" column="user_id"/>
<resultproperty="number" column="number"/>
<associationproperty="user" javaType="cn.itcast.mybatis.po.User">
<!-- 这里的id为user的id,如果写上表示给user的id属性赋值 -->
<id property="id" column="user_id"/>
<resultproperty="username" column="username"/>
<resultproperty="address" column="address"/>
</association>
</resultMap>


(2)调用resultMap:

<select id="findOrdersListResultMap" resultMap="userordermap">
    SELECT
    orders.*,
    user.username,
    user.address
    FROM
    orders,    user
    WHERE orders.user_id = user.id
</select>

(3)定义mapper接口


一对一查询总结:

       个人认为啊,这种情况下使用resultType定义输出映射相对简单,因为这样只需要去添加一个po类就行了,按需求添加额外需要的属性,就可以完成映射。而相对于resultType来说,resultMap就显得稍微麻烦一些了,他需要特别定义resultMap来映射相关联表的实体属性。


二、一对多查询:

1、需求:

       继上面的需求,查询所有订单信息及订单下的订单明细信息(一个订单信息下面或有很多商品,这个女生买护肤品的时候应该很有感触吧。所以订单信息与订单明细是一对多的关系)

(1)确定在数据库执行的sql语句:

Select  orders.*, user.username, user.address,orderdetail.idorderdetail_id,orderdetail.items_id, 
orderdetail.items_num FROM orders,user,orderdetail   
WHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id

执行结果:

(2)定义po类:

public class Orders{
	private Integer id;
	private Integer userId;
	private String number;
	private Date createtime;
	private String note;
	private User user;
	private List<OrderDetial> orderDetails;
	//getter、setter
}


(3)定义resultMap

<!-- 订单信息resultmap -->
<resultMaptype="cn.itcast.mybatis.po.Orders"id="userorderdetailmap">
<id property="id"column="id"/>
<result property="user_id" column="user_id"/>
<result property="number" column="number"/>
<association property="user" javaType="cn.itcast.mybatis.po.User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
</association>
<collectionproperty="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
    <id property="id" column="orderdetail_id"/>
    <result property="items_id" column="items_id"/>
    <result property="items_num" column="items_num"/>
</collection>
</resultMap>

       大家可以跟上面对比一下,这两个resultMap除了对订单详细的映射定义外,其他的是完全一样的,现在问题来了,我们需要重新定义上面重复的映射信息吗?答案是不用,resultMap具有可继承特性,我们只需要继承上面的resultMap(userordermap),然后只定义别的就可以了,如下:

<resultMaptype="cn.itcast.mybatis.po.Orders" id="userorderdetailmap" extends="userordermap">
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
   <id property="id" column="orderdetail_id"/>
   <result property="items_id" column="items_id"/>
   <result property="items_num" column="items_num"/>
</collection>
</resultMap>

使用extends来继承订单信息resultmap:userordermap


(4)实现调用:

<selectid="findOrdersDetailList" resultMap="userorderdetailmap">
    SELECT
    orders.*,
    user.username,
    user.address,
    orderdetail.id orderdetail_id,
    orderdetail.items_id,
    orderdetail.items_num
    FROM orders,user,orderdetail
    WHERE orders.user_id = user.id
    AND orders.id =orderdetail.orders_id
</select>


(5)定义mapper接口:

publicList<Orders>findOrdersDetailList () throws Exception;

(6)来测试一下:

Public void testfindOrdersDetailList()throws Exception{
       //获取session
       SqlSession session = sqlSessionFactory.openSession();
       //获限mapper接口实例
       UserMapper userMapper =session.getMapper(UserMapper.class);
       //查询订单信息
       List<Orders> list =userMapper.findOrdersDetailList();
       System.out.println(list);
       //关闭session
       session.close();
    }

       这个吧,图没有了,可是可以给大家形容一下,就是返回结果只有四个订单信息,然后每个订单信息里面有两个商品信息list压到这里面。就这样,我们就实现了一对多的查询,为什么这个例子我们不用resultType来执行,其实结果早就给大家了,上面执行sql的结果图,就是返回的信息列表,实际上只有四个订单信息,但是使用resultType会返回8条信息,也就是没有完成去重,还需要我们去手动去重,了然了吗?不是很方便


三、多对多查询

(1)需求:

       查询用户购买的商品信息(一个用户可以有N个订单信息,每个订单信息可以有M个商品信息,所以我们需要查询所有的用户信息,关联查询订单及订单明细信息,订单名信息中关联查询商品信息)

(2)确定要执行的sql:

SELECT
         orders.*,
         USER.username,
         USER.address,
         orderdetail.idorderdetail_id,
         orderdetail.items_id,
         orderdetail.items_num,
         items.nameitems_name,
         items.detailitems_detail
FROM
         orders,
         USER,
         orderdetail,
         items
WHERE
         orders.user_id= USER .id
AND orders.id = orderdetail.orders_id
ANDorderdetail.items_id = items.id

(3)po类变化:

       在User中添加List<Orders>orders 属性;在Orders类中加入List<Orderdetail> orderdetails属性;Items类,不用动

(4)定义resultMap:

<resultMap type="cn.itcast.mybatis.po.User"id="userOrderListResultMap">
       <id column="user_id"property="id"/>
       <result column="username"property="username"/>
       <collection property="orders"ofType="cn.itcast.mybatis.po.Orders">
          <id  column="id"property="id"/>
          <result property="number" column="number"/>
          <collection property="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">
               <id  column="orderdetail_id" property="id"/>
               <result property="ordersId"column="id"/>
               <result property="itemsId"column="items_id"/>
               <result property="itemsNum"column="items_num"/>
               <association property="items"javaType="cn.itcast.mybatis.po.Items">
                   <id column="items_id" property="id"/>
                   <result column="items_name" property="name"/>
                   <result column="items_detail" property="detail"/>
              </association>
         </collection>
     </collection>
</resultMap>


(5)调用resultMap:

<select id="findUserItemResultMap" resultMap="UserItemResultMap" >        
       select orders.*,
			  user.username,
			  user.sex,
			  user.address,
			  orderdetail.id,
			  orderdetail_id,
			  orderdetail.items_id,
			  orderdetail.items_num,
			  orderdetail.orders_id,
			  item.id item_id,
			  item.name item_name,
			  item.detail item_detail,
			  item.price item_price 
	   from orders,user,orderdetail,item 
	   where orders.user_id=user.id 
			and orders.id=orderdetail.orders_id 
			and orderdetail.items_id=item.id
</select>

到这里,相信大家能看出点端倪来了吧,我们一直都是用<collection></collection>和<association></association>分别对集合和实体进行关联映射,而且它们层层嵌套的方式就跟实体之间层层嵌套的方式一样:user中包含orders,orders中包含orderdetail,orderdetail中包含item。


(6)然后定义mapper接口:

public interface UserMapper {    List<User> findUserItemResultMap() throws Exception;}

结果,就请大家自己去动手实验一下吧!


到此,我们的Mybatis高级映射之一对一,一对多,多对多映射就分享完了,期间自己又有点收获,总结一下:

1、resultType:将查询结果按照sql列名pojo属性名一致性映射到pojo中。常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

2、resultMap:使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。其中association见关联查询信息映射到一个pojo对象中,collection将关联查询信息映射到一个list集合中然而,使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。那就要看我们自己的判断力了。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 22
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值