.Net转Java自学之路—Mybatis框架篇四(高级映射、延迟加载)
高级映射:
一对一查询:对应表t_Orders、t_User
select t_orders.*,t_user.username,t_user.address from t_orders,t_user where t_orders.user_id=t_user.id
resultType实现方式:
创建一个po类来扩展不属于表t_orders表的字段。
public class OrdersCustom extends Orders{ private String username; private String address; //get()\set()Code... }
mapper.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.ccir.mybatis.mapper.OrdersMapper"> <select id="findOrdersUser" resultType="cn.ccir.mybatis.entity.OrdersCustom"> select t_orders.*,t_user.username,t_user.address from t_orders,t_user where t_orders.user_id=t_user.id </select> </mapper>
mapper接口:
public List<OrdersCustom> findOrdersUser() throws Exception;
resultMap实现方式:
使用resultMap将查询结果中的信息映射到Orders对象中。在Orders实体类中添加User属性,将查询出来的用户信息映射到Orders对象的user属性中。
private User user; //get/set方法Code...
<!-- 定义resultMap --> <resultMap type="cn.ccir.mybatis.entity.Orders" id="OrdersUserResultMap"> <!-- 配置映射的Orders信息,在主表Orders中配置查询列的唯一标识id标签 若有多个列组成唯一标识,则配置多个id --> <id column="id" property="id"/> <result column="user_id" property="userid"/> <result column="note" property="note"/> <!-- .....Orders中的字段和属性...... --> <!-- 配置映射的User信息 association:用于樱色和关联查询单个对象的信息 property:要将关联查询的用户信息映射到Orders中那个属性 --> <association property="user" javaType="cn.ccir.mybatis.entity.User"> <!-- id:关联用户的唯一标识 column:指定唯一标识用户信息的列 property:映射到user的那个属性 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> </resultMap> <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap"> select t_orders.*,t_user.username,t_user.address from t_orders,t_user where t_orders.user_id=t_user.id </select>
public List<Orders> findOrdersUserResultMap() throws Exception;
resultType和resultMap实现一对一查询时,使用resultType实现较为简单。
若pojo中没有查询出来的列名,需要增加列名对应的属性,即可完成映射。若没有查询结果的特殊要求建议使用resultType。
而resultMap需要单独定义resultMap,若有对查询结果有特殊的要求,使用resultMap可以完成,将关联查询映射pojo的属性中。
resultMap可以实现延迟加载。
resultType无法实现延迟加载。
一对多查询:
select t_orders.* ,t_user.username,t_user.address ,t_ordersdetail.item_num,t_ordersdetail.item_name from t_orders,t_user,t_ordersdetail where t_orders.user_id=t_user.id and t_orders.id=t_ordersdetail.order_id
在Orders实体类中添加List的OrderDetail属性:
private List<OrderDetail> orderDetails; //get/set方法Code...
resultMap实现方式:
<!-- 定义resultMap时,使用extends继承,不用再配置orders信息和user信息的映射 --> <resultMap type="cn.ccir.mybatis.entity.Orders" id="OrdersAndOrdersDetail" extends="OrdersUserResultMap"> <!-- 配置orders --> <!-- <id column="id" property="id"/> <result column="user_id" property="userid"/> <result column="note" property="note"/> --> <!-- 配置user --> <!-- <association property="user" javaType="cn.ccir.mybatis.entity.User"> <id column="user_id" javaType="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> --> <!-- 配置ordersdetail 一条orders对应多条ordersdetail,使用collection进行映射 collection:对关联查询到多条记录映射到集合对象中 property;将关联查询到多条记录映射到Orders的ordersDetials属性 ofType:指定映射到集合属性中pojo的类型 --> <collection property="ordersDetails" ofType="cn.ccir.mybatis.entity.OrderDetail"> <!-- id:t_ordersdetail的唯一标识 property:要将t_ordersdetail的唯一标识映射到OrdersDetail的id属性 --> <id column="detail_id" property="id"/> <result column="item_num" property="item_num"/> <result column="item_name" property="item_name"/> </collection> </resultMap> <select id="findOrdersAndOrdersDetail" resultMap="OrdersAndOrdersDetail"> select t_orders.* ,t_user.username,t_user.address ,t_ordersdetail.id detail_id,t_ordersdetail.item_num,t_ordersdetail.item_name from t_orders,t_user,t_ordersdetail where t_orders.user_id=t_user.id and t_orders.id=t_ordersdetail.order_id </select>
public List<Orders> findOrdersAndOrdersDetail() throws Exception;
Mybatis使用collection对关联查询的多条记录映射到一个List集合中。
多对多查询:
select t_orders.* ,t_user.username,t_user.address ,t_ordersdetail.id detail_id,t_ordersdetail.item_num ,t_ordersdetail.item_name ,t_ordersdetail.goods_id ,t_goods.goods_name,t_goods.goods_price from t_orders,t_user,t_ordersdetail,t_goods where t_orders.user_id=t_user.id and t_orders.id=t_ordersdetail.order_id and t_ordersdetail.goods_id=t_goods.id
private List<Orders> orders; //get/set方法Code...
private List<OrdersDetail> orderDetail; //get/set方法Code...
private Goods goods; //get/set方法Code...
<resultMap type="cn.ccir.mybatis.entity.User" id="UserAndGoods"> <!-- 配置User信息 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <!-- 配置Orders信息:一条user信息对应多条orders信息 --> <collection property="orders" ofType="cn.ccir.mybatis.entity.Orders"> <id column="id" property="id"/> <result column="note" property="note"/> </collection> <!-- 配置OrdersDetails信息:一个Orders对应多条OrdersDetail --> <collection property="ordersDetails" ofType="cn.ccir.mybatis.entity.OrderDetail"> <id column="detail_id" property="id"/> <result column="item_num" property="item_num"/> <result column="item_name" property="item_name"/> </collection> <!-- 配置Goods信息 一条OrderDetails信息对应一条Goods信息 --> <association property="goods" javaType="cn.ccir.mybatis.entity.Goods"> <id column="goods_id" property="id"/> <result column="goods_name" property="goods_name"/> <result column="goods_price" property="goods_price"/> </association> </resultMap> <select id="findUserAndGoods" resultMap="UserAndGoods"> select t_orders.* ,t_user.username,t_user.address ,t_ordersdetail.id detail_id,t_ordersdetail.item_num ,t_ordersdetail.item_name ,t_ordersdetail.goods_id ,t_goods.goods_name,t_goods.goods_price from t_orders,t_user,t_ordersdetail,t_goods where t_orders.user_id=t_user.id and t_orders.id=t_ordersdetail.order_id and t_ordersdetail.goods_id=t_goods.id </select>
public List<User> findUserAndGoods() throws Exception;
延迟加载:
resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能。因为查询单表比关联查询多张表速度要快。
使用association实现延迟加载:
需要使用association中的select指定延迟加载去执行的statement的id值。
当需要查询t_orders并且关联t_user信息。
mapper.xml配置:在配置时需要定义俩个mapper的方法对应的statement。先实现对Orders的信息查询。再关联查询User中的信息查询。
<!-- 延迟加载的resultMap --> <resultMap type="cn.ccir.mybatis.entity.Orders" id="OrdersUserLazyLoad"> <id column="id" property="id"/> <result column="user_id" property="userid"/> <result column="note" property="note"/> <!-- 实现对User信息进行延迟加载 select:指定延迟加载需要执行的statement的id(是根据user_id查询User信息statement)。 要使用UserMapper.xml中findUserById完成根据用户id的查询。 若findUserById不再本mapper.xml中需要前面加namespace column:订单信息中关联用户信息查询的列,是user_id --> <association property="user" javaType="cn.ccir.mybatis.entity.User" select="cn.ccir.mybatis.mapper.UserMapper.findUserById" column="user_id"> </association> </resultMap> <select id="findOrdersUserLazyLoad" resultMap="OrdersUserLazyLoad"> select * from t_Orders </select>
public List<Orders> findOrdersUserLazyLoad() throws Exception;
延迟加载配置:
在Mybatis中默认是未开启延迟加载。需要在SqlMapConfig.xml中setting配置开启延迟加载。
lazyLoadingEnabel:全局设置懒加载。若设为false,则所有相关联的都会被初始化加载。默认为:false。
aggressiveLazyLoading:当设置为true时,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。默认为true。
<!-- 开启延迟加载配置 --> <settings> <!-- 打开延迟加载的开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改为消极加载。即按需要加载 --> <setting name="aggressveLazyLoading" value="false"/> </settings>