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

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

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值