mybaties之关联查询与延迟加载

来源:互联网 发布:sor文件打开软件 编辑:程序博客网 时间:2024/05/16 07:05

一Mybaties关联查询与缓存

 

基本数据模型:

如上所示是我们电商系统的基本数据模型

1.1 一对一映射

模拟一个订单只能属于一个用户的,一对一映射。

SELECT orders.`id`, orders.`user_id`, orders.`number`, user.`username`, user.`sex`FROM orders, USERWHERE orders.`user_id` = user.`id`


 

1.1.1 以resultType作为扩展类

创建可扩展的PO类,扩展订单实体:

publicclass OrdersExt extends Orders{       //添加用户属性    /*USER.username,      USER.address */       private String username;    private String address;    public String getUsername() {       returnusername;    }    publicvoid setUsername(String username) {       this.username = username;    }    public String getAddress() {       returnaddress;    }    publicvoid setAddress(String address) {       this.address = address;    }   }


创建mapper映射接口:

public List<OrdersExt> findOrdersUser();

创建映射文件:

<mapper namespace="cn.itcast.mybatis.mapper.OrdersMapper">     <!-- 定义查询订单表列名的SQL片段 -->    <sql id="select_orders">       Orders.id,       Orders.user_id,       orders.number,       orders.createtime,       orders.note    </sql>    <!-- 定义查询用户表列名的SQL片段 -->    <sql id="select_user">       user.username,       user.address    </sql>    <!-- 进行订单信息查询,包括用户的名称和地址信息 -->    <select id="findOrdersUser" resultType="OrdersExt">       Select       <include refid="select_orders"/>       <include refid="select_user"></include>       from orders,user       where orders.user_id = user.id    </select></mapper>


 

加载映射文件

<!-- 批量加载mapper文件,需要mapper接口文件和mapper映射文件名称相同且在同一个包下 --><package name="cn.itcast.mybatis.mapper"/>

测试代码

@Testpublicvoid testFindOrdersUser(){    // 创建sqlSession    SqlSession sqlSession = sqlSessionFactory.openSession();     // 通过SqlSession构造usermapper的代理对象    OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);    // 调用usermapper的方法    List<OrdersExt> list = ordersMapper.findOrdersUser();     System.out.println(list);     // 释放SqlSession    sqlSession.close();}


 

1.1.2 以resultMap作为扩展

 vo实体类

publicclass Orders {    private Integer id;    private Integer userId;    private String number;    private Date createtime;private String note;private User user;


mapper接口:

public List<OrdersExt> findOrdersUserRstMap();<!-- 进行订单信息查询,包括用户的名称和地址信息 (ResultMap)-->    <select id="findOrdersUserRstMap" resultMap="OrdersUserRstMap">       Select       <include refid="select_orders"/>       ,        <include refid="select_user"></include>       from orders,user       where orders.user_id = user.id


xml映射文件

</select>     <!-- 定义orderUserResultMap -->    <resultMap type=" cn.itcast.mybatis.po.Orders" id="OrdersUserRstMap">       <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" />       <!-- 映射一对一关联关系的用户对象-->       <!--           property:指定关联对象要映射到Orders的哪个属性上           javaType:指定关联对象所要映射的java类型         -->       <!-- id标签:指定关联对象结果集的唯一标识,很重要,不写不会报错,但是会影响性能 -->       <association property="user"javaType="cn.itcast.mybatis.po.User">           <id column="user_id"property="id" />           <result column="username"property="username" />           <result column="address"property="address" />       </association>    </resultMap>


 

测试代码

@Testpublicvoid testFindOrdersUserRstMap() {    // 创建sqlSession    SqlSession sqlSession = sqlSessionFactory.openSession();     // 通过SqlSession构造usermapper的代理对象    OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);    // 调用usermapper的方法    List<Orders> list = ordersMapper.findOrdersUserRstMap();          //此处我们采用debug模式来跟踪代码,然后验证结果集是否正确    System.out.println(list);    // 释放SqlSession    sqlSession.close 


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

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

 

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

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

 

1.2 一对多映射

业务场景描述:一个订单有多个订单明细。

Select         Orders.id,         Orders.user_id,         orders.number,orders.createtime,orders.note,user.username,user.address,orderdetail.iddetail_id,orderdetail.items_id,orderdetail.items_numfrom orders,user,orderdetailwhere orders.user_id = user.id         andorders.id = orderdetail.orders_id 


修改订单实体

在Orders类中添加以下属性,并提供get/set方法:

//订单明细private List<Orderdetail> detailList;


 

mapper接口

// 查询订单信息及订单明细信息(一对多映射之使用resultMap)public List<Orders> findOrdersAndOrderdetailRstMap();

编写映射文件Mapper.xml

<!-- 定义OrdersAndOrderdetailRstMap --><!-- extends:继承已有的ResultMap,值为继承的ResultMap的唯一标示 --><resultMap type="Orders"id="OrdersAndOrderdetailRstMap"    extends="OrdersUserRstMap">       <!-- 映射关联关系(一对多) -->       <!-- collection标签:定义一个一对多关系           ofType:指定该集合参数所映射的类型        -->       <collection property="detailList"ofType="Orderdetail">           <id column="detail_id"property="id" />           <result column="items_id"property="itemsId" />           <result column="items_num"property="itemsNum" />       </collection>    </resultMap> <!-- 查询订单信息,包括用户名称、用户地址,订单商品信息(嵌套结果) --><select id="findOrdersAndOrderdetailRstMap"resultMap="OrdersAndOrderdetailRstMap">        Select       <include refid="select_orders"/>,       <include refid="select_user"/>,       orderdetail.id detail_id,       orderdetail.items_id,       orderdetail.items_num       from orders,user,orderdetail       where orders.user_id = user.id       and       orders.id = orderdetail.orders_id     </select>


resultMap的extends属性:可以用此属性来继承一个已有的resultmap。但是它继承的resultMap的type和它本身的type要保持一致。通过resultmap的继承,可以减少mapper的冗余映射。

测试代码
@Testpublicvoid testFindOrdersAndOrderdetailRstMap() {    // 创建sqlSession    SqlSession sqlSession = sqlSessionFactory.openSession();     // 通过SqlSession构造usermapper的代理对象    OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);    // 调用usermapper的方法    List<Orders> list = ordersMapper.findOrdersAndOrderdetailRstMap();          //此处我们采用debug模式来跟踪代码,然后验证结果集是否正确    System.out.println(list);    // 释放SqlSession    sqlSession.close();


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

 

1.3 多对多映射

用户信息与商品信息的多对多关系

select         Orders.id,         Orders.user_id,         orders.number,orders.createtime,orders.note,user.username,user.address,orderdetail.iddetail_id,orderdetail.items_id,orderdetail.items_num items.name items_name, items.detail items_detail FROM orders,USER, orderdetail, itemsWHERE user.`id` = orders.`user_id`  ANDorders.`id` = orderdetail.`orders_id`  ANDorderdetail.`items_id` = items.`id`


 

修改实体信息,分别在用户中添加订单信息,订单中添加订单明细,订单明细中添加订单项

在user类中添加List<Orders> ordersList 属性

// 订单信息private List<Orders> ordersList;


在Orders类中添加List<Orderdetail>属性

//订单明细private List<Orderdetail> detailList;


在Orderdetail类中添加Items属性

//商品信息private Items items;


 

接口定义

//查询用户及用户购买商品信息(多对多映射之使用resultMap)public List<User> findUserAndItemsRstMap();


编写映射文件

<!-- 定义UserAndItemsRstMap -->    <resultMap type="User" id="UserAndItemsRstMap">       <!-- 用户信息 -->       <!-- id:关联查询用户的唯一标示 -->       <id column="user_id"property="id" />       <result column="username"property="username" />       <result column="address"property="address" />       <!-- 订单信息(一个用户有多个订单) -->       <collection property="ordersList"ofType="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="detailList"ofType="orderdetail">              <id column="detail_id"property="id" />              <result column="items_id"property="itemsId" />              <result column="items_num"property="itemsNum" />              <!-- 商品信息(一个订单明细对应一个商品) -->              <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>     <!-- 查询用户及用户购买商品信息(多对多映射之使用resultMap) -->    <select id="findUserAndItemsRstMap" resultMap="UserAndItemsRstMap">       Select       <include refid="select_orders"/>       ,       <include refid="select_user"/>       ,       <include refid="select_orderdetail"></include>       ,       items.name items_name,       items.detail items_detail       from       orders,user,orderdetail,items       where orders.user_id = user.id       and       orders.id = orderdetail.orders_id       and orderdetail.items_id = items.id    </select>


编写测试代码:

@Test    publicvoid testFindUserAndItemsRstMap() {       // 创建sqlSession       SqlSession sqlSession = sqlSessionFactory.openSession();       // 通过SqlSession构造usermapper的代理对象       OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);       // 调用usermapper的方法       List<User> list = ordersMapper.findUserAndItemsRstMap();       // 此处我们采用debug模式来跟踪代码,然后验证结果集是否正确        System.out.println(list);       // 释放SqlSession       sqlSession.close();    }


1.3.1 关联映射总结

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集合中。

 

1.4 延迟加载

resultMap中的association和collection标签具有延迟加载的功能。

延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。需要关联信息时再去按需加载关联信息。这样会大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

Mybatis默认是不开启延迟加载功能的,我们需要手动开启。

需要在SqlMapConfig.xml文件中,在<settings>标签中开启延迟加载功能。

lazyLoadingEnabled、aggressiveLazyLoading

<settings>         <!-- 开启延迟加载,默认是false -->                   <setting name="lazyLoadingEnabled"value="true"/>                   <!--积极的懒加载模式,默认是false-->                   <setting name="aggressiveLazyLoading"value="false"/></settings>


 

<!-- 定义OrdersUserLazyLoadingRstMap --><resultMap type="cn.itcast.mybatis.po.Orders"id="OrdersUserLazyLoadingRstMap">    <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"/>          <!-- 延迟加载用户信息 -->    <!-- select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)       我们使用UserMapper.xml中的findUserById完成根据用户ID(user_id)查询用户信息       如果findUserById不在本mapper中,前边需要加namespace    -->    <!-- column:主信息表中需要关联查询的列,此处是user_id -->    <association property="user" select="cn.itcast.mybatis.mapper.UserMapper.findUserById"column="user_id"></association></resultMap> <!-- 查询订单信息,延迟加载关联查询的用户信息 --><select id="findUserById" parameterType="int"       resultType="cn.itcast.mybatis.po.User">    SELECT * FROM user WHERE id = #{id}</select>


如上图所示通过懒加载关联查询用户信息。

映射文件

<package name="cn.itcast.mybatis.mapper"/>

查询订单信息

// 查询订单信息,延迟加载关联查询的用户信息public List<Orders> findOrdersUserLazyLoading();


 

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 雷克萨斯ux 雷克萨斯ux价格及图片 ux168寄卖网 ux雷克萨斯 雷克萨斯ux260 雷克萨斯ux260h 雷克萨斯ux图片 u3x手机 ux260h u3x ux260h价格 雷克萨斯ux价格 ux是什么意思 机战ux ux是什么 机战ux下载 华硕 ux u信 u钱包上征信吗 u卡贷上征信吗 优信拍 优信拍app 公车拍卖网 2手 u净 u净洗衣 u净app u净洗衣app u段和v段的区别 u段话筒 u段无线话筒怎么调频 无线u段麦克风 什么是u段话筒 u点充值 a点u点g图解图 a点 a点u点g图解图用手 u点是什么 雨的拼音为什么u没有点 u盘系统 u盘启动