20_高级映射:多对多查询
【需求】
查询用户及用户购买的商品信息。
【SQL语句】
查询主表:用户user表
关联表:由于用户和商品没有直接关联,需通过订单和订单明细进行关联,所以关联的表是 orders、orderdetail、items
【映射的思路】
将用户信息映射到user中。
在user类中添加订单列表属性List<Orders> orderlist,将用户创建的订单映射到orderslist。
在Orders中添加订单明细列表属性List<OrderDetail> orderdetails,将订单的明细映射到orderdetails。
在OrderDetails中添加items属性,将订单明细所对应的商品映射到items。
【工程截图】
【Items.java】
package cn.higgin.mybatis.po; import java.util.Date; public class Items { private Integer id; private String name; private Float price; private String pic; private Date createtime; private String detail; //忽略get/set方法....... }
【Orderdetail.java】
package cn.higgin.mybatis.po; public class Orderdetail { private Integer id; private Integer ordersId; private Integer itemsId; private Integer itemsNum; //订单明细对应的商品信息 private Items items; //忽略get/set方法...... }
【】
package cn.higgin.mybatis.po; import java.util.Date; import java.util.List; public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; //引入用户信息 private User user; //引入订单明细(和上面的用户信息不同,一个是一对一,一个是一对多) private List<Orderdetail> orderdetails; //忽略get/set方法...... }
【User.java】
package cn.higgin.mybatis.po; import java.util.Date; import java.util.List; public class User { //属性名和数据库表的字段对应 private int id; private String username; private String sex; private Date birthday; private String address; //用户创建的订单列表 private List<Orders> ordersList; //忽略get/set方法...... }
【OrdersMapperCustom.java】
package cn.higgin.mybatis.mapper; import java.util.List; import cn.higgin.mybatis.po.User; public interface OrdersMapperCustom { //查询用户购买商品信息 public List<User> findUserAndItemsResultMap() throws Exception; }
【OrdersMapperCustom.xml】
<?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"> <mapper namespace="cn.higgin.mybatis.mapper.OrdersMapperCustom"> <!-- 查询用户及购买的商品 --> <resultMap type="cn.higgin.mybatis.po.User" id="UserAndItemsResultMap"> <!-- 1.用户信息 --> <id column="user_id" property="id"/> <id column="username" property="username"/> <id column="sex" property="sex"/> <id column="address" property="address"/> <!-- 2.订单信息 (一个用户对应对个订单,所以用collection映射)--> <collection property="ordersList" ofType="cn.higgin.mybatis.po.Orders"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 订单明细(一个订单包括多个订单明细) --> <collection property="orderdetails" ofType="cn.higgin.mybatis.po.Orderdetail"> <id column="orderdetail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> <result column="orders_id" property="ordersId"/> <!-- 商品信息(一个订单明细对应一个商品) --> <association property="items" javaType="cn.higgin.mybatis.po.Items"> <id column="items_id" property="id"/> <result column="items_name" property="name"/> <result column="items_detail" property="detail"/> <result column="items_price" property="price"/> </association> </collection> </collection> </resultMap> <!-- 查询订单关联查询用户信息,使用resultMap --> <select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap"> SELECT orders.*, USER.username, USER.sex, USER.address, orderdetail.items_id, orderdetail.items_num, orderdetail.orders_id, items.name items_name, items.detail items_detail, items.price items_price FROM orders,USER,orderdetail,items WHERE orders.user_id=user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id=items.id </select> </mapper>
【db.properties和SqlMapConfig.xml与前一篇博文相同】
【OrdersMapperCustomTest.java】
package cn.higgin.mybatis.mapper; import java.io.InputStream; 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.higgin.mybatis.po.User; public class OrdersMapperCustomTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在执行testFindUserById之前执行 @Before public void setUp() throws Exception { // 创建sqlSessionFactory // mybatis配置文件 String resource = "SqlMapConfig.xml"; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 创建会话工厂,传入mybatis的配置文件信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindOrdersUser() throws Exception { SqlSession sqlSession=sqlSessionFactory.openSession(); //创建代理对象 OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class); //调用mapper的方法 List<User> list=ordersMapperCustom.findUserAndItemsResultMap(); System.out.println(list.size()); sqlSession.close(); } }
【运行结果】
【小结】
1.若要实现查询用户购买的商品信息明细清单(用户名、用户地址、购买商品名称、购买时间、购买商品数量)等等,
针对这个需求就可以使用resultType,将查询到的记录映射到一个扩展的pojo中,能方便实现。
2.一对多是多对对的特例,如下需求:
查询用户购买的商品信息,用户和商品的关系时多对多关系。
2.1需求1:
查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(常见的需求,常称为:用户购买商品明细列表)
方法:使用resultType将上边查询列映射到pojo输出。
2.2需求2;
查询字段:用户账号、用户名称、购买商品数量、商品明细
方法;使用resultMap将用户购买的商品明细列表映射到user对象中。
记住:
使用resultMap是针对那些对查询结果映射有特殊要求的功能,比如特殊要求映射成的list中嵌套包括多个list。