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 联结查询:内联结
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 有点类似于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 的便利之一。
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映射进行代码编写, mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。
使用resultType实现: 将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。
实例:查询用户及用户购买商品信息。 查询主表是:user 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表: orders、orderdetail、items 联结查询:内联结
注意:我们在利用多对多的情况下,一定要主要ResultMap的嵌套关系。
