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

来源:互联网 发布:pos机数据库文件名 编辑:程序博客网 时间:2024/05/16 10:03

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

一对一关系(association)

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

方法一(ResultMap)

orders表和实体

Orders表
Order实体

User表

User表
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>

方法二

实体类

OrderCustom

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.

订单明细表和实体

table
订单明细实体

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

0 0