您的位置:首页 > 其它

mybatis--关联映射及延迟加载

2016-03-17 14:28 633 查看
对于hibernate或者EJB等实现了JPA协议的关联映射,大部分都是利用注解或者配置文件。而作为经典的ORM,如果要熟练掌握有些困难,但是基本的掌握还是可以的,hibernate关系映射里边已经介绍了相关的操作。又或者说看看这篇博客:EJB实体映射也详细的介绍了JPA注解映射。那么今天我们就来看一下mybaits这个框架如何帮组我们来实现关联映射。

一对一关系(association)

在mybatis中,如果要实现一对一关系,需要运用association来设置一对一关系,例如订单和用户的关系,一个订单只对应一个用户。数据库和实体设计如下

方法一(ResultMap)

orders表和实体





User表





Mapper.xml

指定输出类型是ResultMap

<!--订单查询关联用户的resultMap 将整个查询的结果映射到com.tgb.mybatis.po.Orders -->
<resultMap type="com.tgb.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 配置订单的信息 -->

<id column="id" property="id" /><!-- 置顶查询列的唯一标识 ,如果有多个列组成唯一标识,就需要配置多个id、 -->
<result column="number" property="number" />
<result column="user_id" property="userId" />
<result column="createtime" property="createtime" />
<result column="note" property="note" />

<!-- 配置订单关联查询用户信息 association:用来映射关联查询单个对象的信息 property:要将关联查询的用户信息映射到Orders中那个属性(user) -->
<association property="user" javaType="com.tgb.mybatis.po.User">
<!-- 关联查询的用户的唯一标识 -->
<!-- column指定唯一标识用于的列 javaType:映射到user实体的那个信息 -->
<id column="user_id" property="id" />
<result column="username" property="username" />
<result column="sex" property="sex" />
<result column="address" property="address" />
</association>
</resultMap>

<!-- 查询定点关联查询用户 使用resultMap -->
<select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
select orders.*,
User.username,
USER.sex,
USER.address
FROM
orders,
User
Where
orders.user_id=user.id

</select>


方法二

实体类



mapper.xml

<!-- 查询定点关联查询用户 -->
<select id="findOrdersUser" resultType="cn.itcast.mybatis.po.OrdersCustom">
select orders.*,
User.username,
USER.sex,
USER.address
FROM
orders,
User
Where
orders.user_id=user.id

</select>


方法一和方法二分别用了ResultMap和ResultType,使用ResultType的好处就是他可以根据查询出来的结果与Custom中对应的字段来组合成新的pojo类,但是使用resultType无法将查询结果映射到pojo对象的pojo属性中,而resultMap可以。使用上根据对结果集查询遍历的需要选择使用resultType还是resultMap。

多对一(colllection)

一个订单可以哟多个订单明细,那么我们就按照订单与订单明细来组合一下resultMap.

订单明细表和实体





mapper.xml

<!--订单查询和订单明细 将整个查询的结果映射到cn.itcast.mybatis.po.Orders -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap"
extends="OrdersUserResultMap">

<!-- 一个订单包含多个订单明细 使用collection查询 collection:将多条信息映射到集合中 property:映射到那个属性
ofType:映射到属性中pjo的类型 -->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<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>
<!-- 查询订单关联和用户和订单明细 -->
<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
SELECT
orders.*, USER.username,
USER.sex,
USER.address,orderdetail.items_id,
orderdetail.id orderdetail_id,
orderdetail.items_num,orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE
orders.user_id = USER.id
AND orderdetail.orders_id =
orders.id
</select>


extends=”OrdersUserResultMap”这句代码是表示继承上边一对一的关联映射,因为我们查询订单详细的时候也是需要查询这个订单是谁的,所以就直接把一对一的查询代码给抽离出来了。

多对多

询用户和购买的商品信息就是一个典型的多对多,例如一个商品可能被多个用户购买,一个用户也可以购买多个信息,所以我们再订单中加入了订单明细的属性:

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


简单的顺一下思路,因为这个多对多可能相对复杂一些。查询用户和购买的商品信息,我们需要返回的是用户的信息,所以我们要再用户中加入Order的集合,那么一个用户对应多个Order,而一个Order又对应多个订单明细,一个订单明细又对应一件商品信息,那么如图



<!-- 查询用户和购买的商品信息 -->
<resultMap type="cn.itcast.mybatis.po.User" id="UserAndItemsResultMap">
<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="cn.itcast.mybatis.po.Orders">
<id column="id" property="id" />
<result column="number" property="number" />
<result column="user_id" property="userId" />
<result column="createtime" property="createtime" />
<result column="note" property="note" />
<!-- 订单明细 -->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<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="cn.itcast.mybatis.po.Items">
<id column="item_id" property="id" />
<result column="item_name" property="name" />
<result column="item_price" property="price" />
<result column="item_detail" property="detail" />

</association>
</collection>
</collection>

</resultMap>

<!-- 查询用户及购买的商品的信息 -->
<select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id
orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE
orders.user_id = user.id AND orderdetail.orders_id=orders.id AND
orderdetail.items_id = items.id
</select>


延迟加载

由于我们的数据量可能会有些大,这个时候我可能不一定要一次性取出全部的数据,或许我只需要一部分,可能我需要订单可用户的所有信息,但是我当前使用的只有订单的信息,用户的信息暂时不用,再hibernate中我们使用延迟加载,其实再mybaitis也是又延迟加载的。

打开延迟加载开关

在SqlMapConfig中添加全局变量来控制延迟加载的开启:



<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>


mapper.xml

<!-- 延迟加载的resultMap -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLoadingResultMap">
<!-- 对订单信息的配置 -->
<id column="id" property="id" />
<result column="number" property="number" />
<result column="user_id" property="userId" />
<result column="createtime" property="createtime" />
<result column="note" property="note" />
<!-- 实现用户的延迟加载 select=""置顶延迟加载的statementid(根据user_id查询用户信息的statement) column=""订单信息中关联用户信息查询的列名即user_id -->
<association property="user" column="user_id"
javaType="cn.itcast.mybatis.po.User" select="cn.itcast.mybatis.mapper.UserMapper.findUserById">
</association>
</resultMap>
<!-- 查询订单关联用户 -->
<select id="findOrdersUserLoading" resultMap="OrdersUserLoadingResultMap">
SELECT * FROM orders
</select>


该statement中的select是只想其他的mapper.xml文件中的一个statementId,这样就能实现我当前只查询订单表的信息,如果需要,我再根据user_id来查询用户的信息。

小结

对于上变的一对一和一对多和多对多,无非就是用到了两个属性,一个是association和collection,association就是吧查询到的关联用户放到一个pojo类中,而collection是把信息放入到List集合中,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jpa 框架