六 mybatis高级映射(一对一,一对多,多对多)

1  订单商品数据模型

以订单商品数据为模型,来对mybaits高级关系映射进行学习。

1.1     数据模型分析思路

 

1、每张表记录的数据内容

         分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程。

2、每张表重要的字段设置

         非空字段、外键字段

3、数据库级别表与表之间的关系

         外键关系

4、表与表之间的业务关系

         在分析表与表之间的业务关系时一定要建立 在某个业务意义基础上去分析。

 

1.2     数据模型分析

用户表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表建立 关系。

sqlMapConfig.xml配置

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6 
 7     <!-- 加载属性文件 -->
 8     <properties resource="db.properties">
 9         <!--properties中还可以配置一些属性名和属性值  -->
10         <!-- <property name="jdbc.driver" value=""/> -->
11     </properties>
12         
13     <!-- 和spring整合后 environments配置将废除-->
14     <environments default="development">
15         <environment id="development">
16         <!-- 使用jdbc事务管理,事务控制由mybatis-->
17             <transactionManager type="JDBC" />
18         <!-- 数据库连接池,由mybatis管理-->
19             <dataSource type="POOLED">
20                 <property name="driver" value="${jdbc.driver}" />
21                 <property name="url" value="${jdbc.url}" />
22                 <property name="username" value="${jdbc.username}" />
23                 <property name="password" value="${jdbc.password}" />
24             </dataSource>
25         </environment>
26     </environments>
27     <!-- 加载 映射文件 -->
28     <mappers>
29         
30         <!--通过resource方法一次加载一个映射文件 -->
31         <!-- <mapper resource="mapper/UserMapper.xml"/> -->
32         
33         <!-- 通过mapper接口加载单个 映射文件
34         遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
35         上边规范的前提是:使用的是mapper代理方法
36          -->
37         <!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> -->
38         
39         <!-- 批量加载mapper
40         指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
41         遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
42         上边规范的前提是:使用的是mapper代理方法
43          -->
44         <package name="cn.itcast.mapper"/>
45 
46     </mappers>
47     
48 </configuration>
View Code

 

1       一对一查询

1.1     需求

 

查询订单信息,关联查询创建订单的用户信息

 

1.2     resultType

1.2.1     sql语句

确定查询的主表:订单表

确定查询的关联表:用户表

         关联查询使用内链接?还是外链接?

         由于orders表中有一个外键(user_id),通过外键关联查询用户表只能查询出一条记录,可以使用内链接。

1 select 
2     orders.*,
3     user.username,
4     user.sex,
5     user.address 
6 from 
7     orders,
8     user
9 where orders.user_id=user.id 

 

1.2.2     创建pojo

将上边sql查询的结果映射到pojo中,pojo中必须包括所有查询列名。

原始的Orders.java不能映射全部字段,需要新创建的pojo。

创建 一个pojo继承包括查询字段较多的po类。

 1 //通过此类映射订单和用户查询结果,让此类继承包括 字段较多的pojo类
 2 public class OrdersCustom extends Orders {
 3        
 4     //添加用戶属性
 5     /*  user.username,
 6            user.sex,
 7         user.address  */
 8     
 9     private String username;
10 
11     private String sex;
12 
13     private String address;
14         

 

1.2.3     mapper.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="cn.itcast.mapper.OrdersMapperCustom">
 6     <select id="findOrdersUser" resultType="cn.itcast.po.OrdersCustom">
 7         select 
 8             orders.*,
 9             user.username,
10             user.sex,
11             user.address 
12         from 
13             orders,
14             user
15         where orders.user_id=user.id 
16     </select>
17 
18 </mapper>

 

1.2.4     mapper.java

1 public interface OrdersMapperCustom {
2     
3     //查询订单管理查询的用户信息
4     public List<OrdersCustom> findOrdersUser() throws Exception;
5     
6 }

 

 

1.3     resultMap

1.3.1     sql语句

同resultType实现的sql

 

1.3.2     使用resultMap映射的思路

使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。

 

1.3.3     需要Orders类中添加user属性

1 public class Orders {
2     private Integer id;
3     private Integer userId;
4     private String number;
5     private Date createtime;
6     private String note;
7     
8     private User user;
9     

 

1.3.4     mapper.xml

1.3.4.1              定义resultMap

 1 <!-- 订单查询关联用户的resultMap
 2     将整个查询的结果映射到cn.itcast.mybatis.po.Orders中
 3      -->
 4     <resultMap type="cn.itcast.po.Orders" id="OrdersUserResultMap">
 5         <!-- 配置映射的订单信息 -->
 6         <!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
 7             column:订单信息的唯 一标识 列
 8             property:订单信息的唯 一标识 列所映射到Orders中哪个属性
 9           -->
10         <id column="id" property="id"/>
11         <result column="user_id" property="userId"/>
12         <result column="number" property="number"/>
13         <result column="createtime" property="createtime"/>
14         <result column="note" property="note"/>
15         
16         <!-- 配置映射的关联的用户信息 -->
17         <!-- association:用于映射关联查询单个对象的信息
18         property:要将关联查询的用户信息映射到Orders中哪个属性
19          -->
20         <association property="user"  javaType="cn.itcast.po.User">
21             <!-- id:关联查询用户的唯 一标识
22             column:指定唯 一标识用户信息的列
23             javaType:映射到user的哪个属性
24              -->
25             <id column="user_id" property="id"/>
26             <result column="username" property="username"/>
27             <result column="sex" property="sex"/>
28             <result column="address" property="address"/>
29         
30         </association>
31     </resultMap>

 

1.3.4.2              statement定义

 1 <!-- 查询订单关联查询用户信息,使用resultmap -->
 2 <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
 3         SELECT
 4         orders.*,
 5         USER.username,
 6         USER.sex,
 7         USER.address
 8         FROM
 9         orders,
10         USER
11         WHERE orders.user_id = user.id
12 </select>

 

1.3.5     mapper.java

1 //查询订单关联查询用户使用resultMap
2 public List<Orders> findOrdersUserResultMap()throws Exception;

 

1.4     resultType和resultMap实现一对一查询小结

实现一对一查询:

resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。

如果没有查询结果的特殊要求建议使用resultType。

 

resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。

 

resultMap可以实现延迟加载,resultType无法实现延迟加载。

 

 

2       一对多查询

2.1     需求

查询订单及订单明细的信息。

 

2.2     sql语句

确定主查询表:订单表

确定关联查询表:订单明细表

在一对一查询基础上添加订单明细表关联即可。

 1 select 
 2     orders.*,
 3     user.username,
 4     user.sex,
 5     user.address ,
 6     orderdetail.id orderdetail_id,
 7     orderdetail.items_id,
 8     orderdetail.items_num,
 9     orderdetail.orders_id
10 from 
11     orders,
12     user,
13     orderdetail
14 where orders.user_id=user.id and orders.id=orderdetail.orders_id

 

2.3     分析

使用resultType将上边的 查询结果映射到pojo中,订单信息的就是重复。

 

要求:

对orders映射不能出现重复记录。

 

在orders.java类中添加List<orderDetail> orderDetails属性。

最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderDetails属性中

 

映射成的orders记录数为两条(orders信息不重复)

每个orders中的orderDetails属性存储了该 订单所对应的订单明细。

 

2.4     在orders中添加list订单明细属性

 

 1 public class Orders {
 2     private Integer id;
 3     private Integer userId;
 4     private String number;
 5     private Date createtime;
 6     private String note;
 7     
 8     //用户信息
 9     private User user;
10     
11     //订单明细
12     private List<Orderdetail> orderdetails;

 

2.5     mapper.xml

 1     <select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
 2         SELECT 
 3           orders.*,
 4           USER.username,
 5           USER.sex,
 6           USER.address,
 7           orderdetail.id orderdetail_id,
 8           orderdetail.items_id,
 9           orderdetail.items_num,
10           orderdetail.orders_id
11         FROM
12           orders,
13           USER,
14           orderdetail
15         WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
16     </select>

 

2.6     resultMap定义

 1     <!-- 订单及订单明细的resultMap
 2     使用extends继承,不用在中配置订单信息和用户信息的映射
 3      -->
 4     <resultMap type="cn.itcast.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
 5         <!-- 订单信息 -->
 6         <!-- 用户信息 -->
 7         <!-- 使用extends继承,不用在中配置订单信息和用户信息的映射 -->
 8         
 9         
10         <!-- 订单明细信息
11         一个订单关联查询出了多条明细,要使用collection进行映射
12         collection:对关联查询到多条记录映射到集合对象中
13         property:将关联查询到多条记录映射到cn.itcast.po.Orders哪个属性
14         ofType:指定映射到list集合属性中pojo的类型
15          -->
16          <collection property="orderdetails" ofType="cn.itcast.po.Orderdetail">
17              <!-- id:订单明细唯 一标识
18              property:要将订单明细的唯 一标识 映射到cn.itcast.po.Orderdetail的哪个属性
19                -->
20              <id column="orderdetail_id" property="id"/>
21              <result column="items_id" property="itemsId"/>
22              <result column="items_num" property="itemsNum"/>
23              <result column="orders_id" property="ordersId"/>
24          </collection>
25         
26     </resultMap>

 

2.7     mapper.java

1 //查询订单(关联用户)及订单明细
2     public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;

 

2.8     小结

mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。

 

使用resultType实现:

将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。

 

3       多对多查询

 

3.1     需求

查询用户及用户购买商品信息。

 

3.2     sql语句

查询主表是:用户表

关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:

orders、orderdetail、items

 1 select 
 2     orders.*,
 3     user.username,
 4     user.sex,
 5     user.address ,
 6     orderdetail.id orderdetail_id,
 7     orderdetail.items_id,
 8     orderdetail.items_num,
 9     orderdetail.orders_id,
10     items.name items_name,
11    items.detail items_detail,
12    items.price items_price
13 from 
14     orders,
15     user,
16     orderdetail,
17     items
18 where orders.user_id=user.id and orders.id=orderdetail.orders_id and orderdetail.items_id = items.id

 

3.3     映射思路

 

将用户信息映射到user中。

在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist

在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials

在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items

 

3.4     mapper.xml

 

 1     <!-- 查询用户及购买的商品信息,使用resultmap -->
 2     <select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
 3         SELECT 
 4           orders.*,
 5           USER.username,
 6           USER.sex,
 7           USER.address,
 8           orderdetail.id orderdetail_id,
 9           orderdetail.items_id,
10           orderdetail.items_num,
11           orderdetail.orders_id,
12           items.name items_name,
13           items.detail items_detail,
14           items.price items_price
15         FROM
16           orders,
17           USER,
18           orderdetail,
19           items
20         WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
21     </select>

 

3.5     resultMap定义

 1 <!-- 查询用户及购买的商品 -->
 2     <resultMap type="cn.itcast.po.User" id="UserAndItemsResultMap">
 3         <!-- 用户信息 -->
 4         <id column="user_id" property="id"/>
 5         <result column="username" property="username"/>
 6         <result column="sex" property="sex"/>
 7         <result column="address" property="address"/>
 8         
 9         <!-- 订单信息
10         一个用户对应多个订单,使用collection映射
11          -->
12          <collection property="ordersList" ofType="cn.itcast.po.Orders">
13              <id column="id" property="id"/>
14              <result column="user_id" property="userId"/>
15             <result column="number" property="number"/>
16             <result column="createtime" property="createtime"/>
17             <result column="note" property="note"/>
18             
19              <!-- 订单明细
20          一个订单包括 多个明细
21           -->
22               <collection property="orderdetails" ofType="cn.itcast.po.Orderdetail">
23                       <id column="orderdetail_id" property="id"/>
24                      <result column="items_id" property="itemsId"/>
25                      <result column="items_num" property="itemsNum"/>
26                      <result column="orders_id" property="ordersId"/>
27                      
28                      <!-- 商品信息
29               一个订单明细对应一个商品
30                -->
31                    <association property="items" javaType="cn.itcast.po.Items">
32                        <id column="items_id" property="id"/>
33                        <result column="items_name" property="name"/>
34                        <result column="items_detail" property="detail"/>
35                        <result column="items_price" property="price"/>
36                    </association>
37                      
38               </collection>
39          </collection>
40     </resultMap>

 

3.6     mapper.java

1 //查询用户购买商品信息
2     public List<User>  findUserAndItemsResultMap()throws Exception;

 

3.7     多对多查询总结

 

将查询用户购买的商品信息明细清单,(用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)

 

针对上边的需求就使用resultType将查询到的记录映射到一个扩展的pojo中,很简单实现明细清单的功能。

 

一对多是多对多的特例,如下需求:

查询用户购买的商品信息,用户和商品的关系是多对多关系。

需求1:

查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)

企业开发中常见明细列表,用户购买商品明细列表,

使用resultType将上边查询列映射到pojo输出。

 

需求2:

查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)

使用resultMap将用户购买的商品明细列表映射到user对象中。

 

总结:

 

使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多个list。

 

 

4       resultMap总结

 

resultType:

作用:

         将查询结果按照sql列名pojo属性名一致性映射到pojo中。

场合:

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

 

resultMap:

         使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

 

association:

作用:

         将关联查询信息映射到一个pojo对象中。

场合:

         为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。

         使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。

        

collection:

作用:

         将关联查询信息映射到一个list集合中。

场合:

         为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。

         如果使用resultType无法将查询结果映射到list集合中。

项目源码:

链接:http://pan.baidu.com/s/1pL8iokz 密码:j331

posted @ 2016-11-05 12:23  海天依色  阅读(427)  评论(0编辑  收藏  举报