MyBatis关系映射
2017-07-12 18:32
281 查看
概述+数据模型
Mybatis关系映射主要是包括一对一,一对多,多对一,和多对多关系。再进行我们关系映射的时候,我们需要有一个数据模型来模拟我们对应的相应关系,我们采用的数据模型为用户和订单,订单和订单明细,以及商品之间的关系。
数据库表:
用户表user:记录了购买商品的用户信息。订单表orders:记录了用户所创建的订单(购买商品的订单)。
订单明细表orderdetail:记录了订单的详细信息即购买商品的信息。
商品表items:记录商品信息。
数据模型图:
数据表之间的关系:
先分析数据级别之间有关系的表之间的业务关系:usre和orders:
user —-> orders:一个用户可以创建多个订单,一对多
orders —-> user:一个订单只由一个用户创建,一对一
orders和orderdetail:
orders —-> orderdetail:一个订单可以包括 多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多关系。
orderdetail —-> orders:一个订单明细只能包括在一个订单中,一对一
orderdetail和itesm:
orderdetail —-> itesms:一个订单明细只对应一个商品信息,一对一
items —-> orderdetail:一个商品可以包括在多个订单明细 ,一对多
再分析数据库级别没有关系的表之间是否有业务关系:
orders和items:
orders和items之间可以通过orderdetail表建立 关系。
一对一查询
实例:查询订单信息,关联查询创建订单的用户信息。SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE orders.user_id = user.id
主查询表:orders
关联查询表:user
联结查询:内联结
利用ResultType
1、SQL语句的书写要领:先确定查询的主表,在确定查询的关联表,关联查询是使用内联结还是外联结。2、POVO扩展类创建。(这是由于关联查询出来的信息是多张表的综合字段,所以我们可以根据POJO创建我们的扩展类)
3、Mapper.xml和Mapper.java的代理编写
4、进行测试
相关代码:
// POJO基础类 public class Orders { private int id; private int userid; // private int user_id; private String number; private Date createtime; private String note; } // POVO扩展类 Orders的扩展类,通过此类可以映射订单和用户查询的结果。 public class OrdersExtends extends Orders{ private String username; private String sex; private String address; } // Mapper.xml配置 <select id="findorderanduser" resultType="com.wf.model.OrdersExtends"> SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE orders.user_id = user.id </select> //Mapper.java 代理接口 public interface OrdersExtendsMapper { public List<OrdersExtends> findorderanduser(); } //测试代码 @Test public void testOrdersExtendsMapper() { SqlSession session = sqlsessionfactory.openSession(); OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class); List<OrdersExtends> list = orderextendsmapper.findorderanduser(); for(OrdersExtends o :list){ System.out.println(o.getId()+":"+o.getUserid()+":"+o.getUsername()+":"+o.getAddress()); //System.out.println(o.getId()+":"+o.getUser_id()+":"+o.getUsername()+":"+o.getAddress()); //getUserid没有和数据库对应,所以无法获取默认为0 } }
注意:上述测试代码中,由于userid没有和数据库中的字段进行对应(user_id),所以会造成数据映射不成功而默认为0
利用ResultMap
思路:利用 ResultMap 有点类似于Hibernate中POJO类中的设置。将我们对应的属性关联到类中。1、使用resultMap将查询结果中的订单信息映射到Orders对象中,
2、在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。
// POJO基础类 public class Orders { private User user; // 在Orders类中配置我们的User属性 private int id; private int userid; private String number; private Date createtime; private String note; } // Mapper.xml public interface OrdersExtendsMapper { public List<Orders> findorderanduserResultMap(); } // Mapper.java <mapper namespace="com.wf.dao.OrdersExtendsMapper"> <!-- 订单查询关联用户的查询 --> <resultMap type="com.wf.model.Orders" id="OrderUserResultMap"> <!-- 配置映射的订单信息 --> <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"/> <!-- 配置关联的用户信息 association:用来映射关联查询单个对象的信息 property :将关联信息映射到Order的哪个属性中去 javaType 映射到那个java类中 --> <association property="user" javaType="com.wf.model.User"> <!-- id 关联查询用户的唯一标识 ,外键 column 指定唯一标识用户信息的字段,property表示类中属性 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </association> </resultMap> <select id="findorderanduserResultMap" resultMap="OrderUserResultMap"> SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE orders.user_id = user.id </select> </mapper>
说明:
利用 ResultMap,我们可以利用其中的association 属性将外键关联的相关类进行映射。这也是使用ResultMap 的便利之一。
ResultType和ResultMap实现一对一查询比较
1、resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。2、resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。
3、resultMap可以实现延迟加载,resultType无法实现延迟加载。
一对多查询
实例:查询订单及订单明细的信息。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
主查询表:orders
确定关联查询表:orderdetail
联结查询:内联结
利用resultType将上边的 查询结果映射到pojo中,订单信息的就是重复。而我们对于对orders映射不能出现重复记录。所以我们这里只能利用ResultMap。
利用ResultMap
// POJO类 public class User { private int id; private String username; private Date birthday; private String address; private String sex; } public class Orders { private User user; private int id; private int userid; private String number; private Date createtime; private String note; private List<OrdersDetail> orderdetails; // 一对多关系设置 } public class OrdersDetail { private int id; private int ordersId; private int itemsId; private int itemsNum; } //Mapper.java public interface OrdersExtendsMapper { // 查询订单(关联用户)订单明细 public List<Orders> findOrderAndDetailResultMap(); } //Mapper.xml <resultMap type="com.wf.model.Orders" id="findOrderAndDetailResultMap" > <!-- 配置映射的订单信息 --> <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"/> <!-- 配置关联的用户信息 association:用来映射关联查询单个对象的信息 一对多的逆向使用 property :将关联信息映射到Order的哪个属性中去 javaType 映射到那个java类中 --> <association property="user" javaType="com.wf.model.User"> <!-- id 关联查询用户的唯一标识 ,外键 column 指定唯一标识用户信息的列 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </association> <!-- 订单明细信息 一个订单包含多条明细,要使用collection进行映射 一对多使用 配置在一的一方添加属性 collection:对关联查询的多条记录映射到集合对象中去 property: 将关联查询出来的多条记录映射到类中的那个属性中 list ofType : 指定映射到集合属性中的pojo类,list的泛型 --> <collection property="orderdetails" ofType="com.wf.model.OrdersDetail"> <!-- id 订单明细唯一标识 --> <id column="orderdetail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> <result column="orders_id" property="ordersId"/> </collection> </resultMap> // 测试代码 @Test public void testfindOrderAndDetailResultMap() { SqlSession session = sqlsessionfactory.openSession(); OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class); List<Orders> list = orderextendsmapper.findOrderAndDetailResultMap(); // 断点查看,打印查询4条,list存储2条,自动去重了 for(Orders o :list){ System.out.println(o.getId()+":"+o.getUser().getId()+":"+o.getUser().getUsername()+":"+o.getUser().getAddress()); } }
注意:对于一对多或者多对一的查询,建议使用ResultMap映射进行代码编写,
mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。
使用resultType实现:
将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。
多对多查询
实例:查询用户及用户购买商品信息。查询主表是:user
关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:
orders、orderdetail、items
联结查询:内联结
利用ResultMap
// POJO类 public class User { private int id; private String username; private Date birthday; private String address; private String sex; private List<Orders> orderslist; //一对多 } public class Orders { private User user; // 用户信息 private int id; private int userid; private String number; private Date createtime; private String note; private List<OrdersDetail> orderdetails; //商品信息存放集合 } public class OrdersDetail { private int id; private int ordersId; private int itemsId; private int itemsNum; private Items items; //商品信息 } public class Items { private int id; private String name; private double price; private String detail; private String pic; private Date createtime; } // Mapper.java public interface OrdersExtendsMapper { public List<User> findUserAndItemResultMap(); } //Mapper.xml <!-- 用户及用户购买的商品明细 --> <resultMap type="com.wf.model.User" id="UserAndItemResultMap"> <!-- 映射用户信息 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <!-- 订单信息 一个用户创建多个订单 使用collection --> <collection property="orderslist" ofType="com.wf.model.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="com.wf.model.OrdersDetail"> <!-- id 订单明细唯一标识 --> <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="com.wf.model.Items"> <id column="items_id" property="id"/> <result column="items_name" property="name"/> <result column="item_price" property="price"/> <result column="item_datail" property="detail"/> </association> </collection> </collection> </resultMap> //测试代码 @Test public void testfindUserAndItemResultMap() { SqlSession session = sqlsessionfactory.openSession(); OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class); List<User> list = orderextendsmapper.findUserAndItemResultMap(); for(User o :list){ System.out.println(o.getId()+":"+o.getUsername()+":"+o.getAddress() +":"+o.getOrderslist().get(0).getOrderdetails().get(0).getItems().getName()); } }
注意:我们在利用多对多的情况下,一定要主要ResultMap的嵌套关系。
相关文章推荐
- Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系
- mybatis 一对多的映射关系
- mybatis对象之间映射关系以及数据库表建立的时候外键的添加
- MyBatis中多对多关系的映射和查询
- mysql数据库日期设计以及mybatis映射文件和实体属性的关系
- Mybatis的注解应用之关系映射
- MyBatis一对一和一对多的关系映射(员工和部门)
- Mybatis的关系映射和相应的配置文件
- 【mybatis】【对象属性关系的映射】
- 【MyBatis】关系映射
- mybatis 多对多映射关系
- mybatis的一对一,一对多的关系映射配置及性能分析(延迟加载)
- mybatis对象之间映射关系以及数据库表建立的时候外键的添加
- mybatis对象之间映射关系以及数据库表建立的时候外键的添加
- Mybatis 一对多(OneToOne)关系映射
- mybatis整合spring 之 基于接口映射的多对一关系
- Mybatis框架中实现双向一对多关系映射
- mybatis关系映射之一对多和多对一
- mybatis对象之间映射关系以及数据库表建立的时候外键的添加
- MyBatis关系映射之一对一