12-MyBatis02

Posted rqy0526

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了12-MyBatis02相关的知识,希望对你有一定的参考价值。

今日知识

1. 关联查询
2. 延时加载
3. 查询缓存

关联查询

1.一对一 resultType实现

1. 写个定单的扩展类
    public class OrdersExt extends Orders 
    private String username;
    private String address;
2. 声明定单接口
    public interface OrdersMapper 
    //根据订单id查询订单信息
    public OrdersExt findOrdersUser(int id);

3. 声明定单配置文件
    <mapper namespace="com.rqy.mapper.OrdersMapper">
    <sql id="select_orders">
        orders.id,
        orders.number,
        orders.createtime,
        orders.note,
    </sql>
    <sql id="select_user">
        user.username,
        user.address
    </sql>
    <select id="findOrdersUser" parameterType="int" resultType="ordersExt">
        SELECT
        <include refid="select_orders"/>
        <include refid="select_user"/>
        FROM
        orders,user
        WHERE
        orders.user_id=user.id and orders.id=#?;
    </select>
    </mapper>
4. 加载映射文件
    <mappers>
        <package name="com.rqy.mapper"/>
    </mappers>
5. 测试
    @Test
    public void test()
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        OrdersExt ordersExt = ordersMapper.findOrdersUser(3);
        System.out.println(ordersExt);
        sqlSession.commit();

    
6. 一对一 resultMap实现
     <!--一对一 resultMap实现-->
    <resultMap id="ordersRsMap" type="orders">
        <id column="id" property="id"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!--关联内部对象,Orders类有User user-->
        <association property="user" javaType="com.rqy.model.User">
            <id property="id" column="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
    <select id="findOrdersByRsMap" parameterType="int" resultMap="ordersRsMap">
        SELECT
        <include refid="select_orders"/>
        <include refid="select_user"/>
        FROM
        orders,user
        WHERE
        orders.user_id=user.id and orders.id=#?;
    </select>

2.一对多 resultType实现

1. 在Orders中添加定单明细
    private List<Orderdetail> orderdetails;

    public List<Orderdetail> getOrderdetails() 
        return orderdetails;
    

    public void setOrderdetails(List<Orderdetail> orderdetails) 
        this.orderdetails = orderdetails;
    
2. Mapper接口
     //根据订单id查询订单信息,包括订单项
    public Orders findOrdersByRsMap2(int ordersId);
3. OrderMapper.xml
    <!--一对多resultMap实现-->

    <resultMap id="ordersRsMap2" type="orders">
        <id column="id" property="id"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!--关联内部对象-->
        <association property="user" javaType="com.rqy.model.User">
            <id  column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
        </association>
        <!--集合映射-->
        <collection property="orderdetails" ofType="orderdetail">
            <id column="detail_id" property="id"/>
            <result column="items_id" property="itemsId"/>
            <result column="items_num" property="itmesNum"/>
        </collection>
    </resultMap>
    <select id="findOrdersByRsMap2" parameterType="int" resultMap="ordersRsMap2">
        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
        and orders.id=#?;
    </select>
4.  测试
    //一对一多resultMap实现
    @Test
    public void test2()
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        Orders order = ordersMapper.findOrdersByRsMap2(3);
        System.out.println(order);
    
5. 总结:mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性
中。

3.多对多 resultType实现

1. 将用户信息映射到user中。
* 在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist
* 在Orders中添加订单明细列表属性List<Orderdetail> detailList,将订单的明细映射到detailList
* 在Orderdetail中添加Items属性,将订单明细所对应的商品映射到Items
2. Mapper.xml
//查询用户信息及用户购买的商品信息
    public List<User> findUserAndItemsRslMap();
3. UserMapper.xml
<!--查询用户购买的商品信息,多对多-->
<resultMap id="userAndItemsRslMap" type="user">
    <id  column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="address" property="address"/>
    <!--1.User里面的orderlist属性-->
    <collection property="orderslist" ofType="orders">
        <id column="orders_id" property="id"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>

        <!--2.Order里面的orderdetail属性-->
        <collection property="orderdetails" ofType="orderdetail">
            <id column="detail_id" property="id"/>
            <result column="items_id" property="itemsId"/>
            <result column="items_num" property="itmesNum"/>

            <!--orderdetail里面的items属性-->
            <association property="items" javaType="items">
                <id column="items_id" property="id"/>
                <result column="items_name" property="name"/>
                <result column="items_detail" property="detail"/>
                <result column="items_price" property="price"/>
            </association>
        </collection>
    </collection>
</resultMap>
<select id="findUserAndItemsRslMap" resultMap="userAndItemsRslMap">
    SELECT
        user.id,
        user.username,
        user.address,
        orders.id orders_id,
        orders.number,
        orders.createtime,
        orders.note,
        orderdetail.id detail_id,
        orderdetail.items_id,
        orderdetail.items_num,
        items.name items_name,
        items.detail items_detail,
        items.price items_price
    FROM
    orders,user,orderdetail,items
    WHERE
    orders.user_id=user.id
    and orders.id=orderdetail.orders_id
    and orderdetail.items_id=items.id;
</select>
4. 测试
//多对多resultMap实现
@Test
public void test3()
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userAndItemsRslMap = userMapper.findUserAndItemsRslMap();

for (User user : userAndItemsRslMap) 
    System.out.println("用户名:"+user.getUsername()+"-地址:"+user.getAddress());
    for (Orders order : user.getOrderslist())
        System.out.println("订单id:"+order.getId());
        System.out.println("订单number:"+order.getNumber());
        System.out.println("订单时间:"+order.getCreatetime());
        System.out.println("----------------------------------------");
        for (Orderdetail orderdetail : order.getOrderdetails()) 
            System.out.println();
            System.out.println("商品数量:"+orderdetail.getItmesNum());
            System.out.println("商品名称:"+orderdetail.getItems().getName());
            System.out.println("商品详情:"+orderdetail.getItems().getDetail());
            
    


延时加载

* 分次查询:支持懒加载
* 连接查询:不支持懒加载
1. 概念:延迟加载又叫懒加载,也叫按需加载。
    也就是说先加载主信息,在需要的时候,再去加载从信息。
2. 在mybatis中,resultMap标签的association标签和
    collection标签具有延迟加载的功能。
3. 案例
    1. OrdersMapper.java
     //懒加载订单和用户信息
    public List<Orders> findOrderAndUserByLazyLoading();
    2. OrderMapper.xml配置
     <!--==============懒加载==================-->
    <resultMap id="LazyLoadingordersRsMap" type="orders">
        <id column="id" property="id"/>
        <result column="user_id" property="user_id"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!--关联内部对象 ,支持懒加载-->
        <association property="user" select="com.rqy.mapper.UserMapper.findUserById" column="user_id">
        </association>
    </resultMap>
    <select id="findOrderAndUserByLazyLoading" resultMap="LazyLoadingordersRsMap">
        SELECT * FROM  orders
    </select>
    3. SqlMapConfig.xml
        !--配置懒加载-->
        <settings>
            <setting name="lazyLoadingEnabled" value="true"/>
        </settings>
    4. 测试
         //懒加载
    @Test
    public void test4()
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<Orders> ordersList = ordersMapper.findOrderAndUserByLazyLoading();
        for (Orders order : ordersList) 
            System.out.println("订单号:"+order.getNumber());
            System.out.println("订单所属人:"+order.getUser().getUsername());
            System.out.println("========================");
        
    
    5. 注意:association和collection:添加一个标签:当配置了lazyLoadingEnabled=true后,所有的分次查询都是懒加载,使用fetchType="eager",可以修改懒加载为立即加载

查询缓存

1. 概念:Mybatis的缓存,包括一级缓存和二级缓存,一级缓存是默认使用的。二级缓存需要手动开启。
2. 一级缓存
    * 概念:一级缓存指的就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。
    * 案例:
    1. @Test
    public void test()
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(35);
        System.out.println(user);
        System.out.println("======================");
        //查询两次该用户信息,第二次不会执行sql语句
        User user2 = mapper.findUserById(35);
        System.out.println(user2);
    
    2. 如果一旦执行完修改,添加,删除用户执行完commit,就会清空一级缓存。
     @Test
    public void test2()
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(35);
        System.out.println(user);
       //保存,删除,更新会消除一级缓存
        User u=new User("123","男",new Date(),"河南");
        mapper.insertUser(u);
        //第二次不会执行sql语句
        User user2 = mapper.findUserById(35);
        System.out.println(user2);
    
3. 二级缓存
    * 概念:二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。
    1. 步骤一:User序列化public class User implements Serializable 
    2. <settings>
        <!--二级缓存开关-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    3. UserMapper中配置 二级缓存
          <!--默认使用perpetualCache-->
            <cache></cache>
    4. 测试
        //二级缓存
    //查询
    @Test
    public void test3()
        SqlSession sqlSession1=ssf.openSession();
        SqlSession sqlSession2=ssf.openSession();
        SqlSession sqlSession3=ssf.openSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper mapper2= sqlSession2.getMapper(UserMapper.class);
        UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class);

        User user = mapper1.findUserById(35);
        System.out.println(user);
        sqlSession1.close();
        //添加,删除,修改提交后,会清空二级缓存
        mapper3.insertUser(user);
        sqlSession3.commit();
        //第二次不会执行sql语句
        User user2 = mapper2.findUserById(35);
        System.out.println(user2);
    
    5. 禁用指定方法二级缓存
        select标签中加入:useCache="false"
    6. 刷新缓存
        select,insert,update,加入flushCache="false",此时添加,删除,修改提交后,不会清空二级缓存,默认情况下:flushCache="true".

以上是关于12-MyBatis02的主要内容,如果未能解决你的问题,请参考以下文章

阶段3 1.Mybatis_12.Mybatis注解开发_8 mybatis注解开发使用二级缓存

MyBatis学习12MyBatis中的一级缓存

MyBatis学习12MyBatis中的一级缓存

阶段3 1.Mybatis_12.Mybatis注解开发_1 mybatis注解开发的环境搭建

Mybatis从入门到精通系列 12——Mybatis 的一级缓存与二级缓存

阶段3 1.Mybatis_12.Mybatis注解开发_7 Mybatis注解开发一对多的查询配置