MyBatis结果映射与MyBatis缓存初探学习记录

MyBatis高级结果映射(一对一、一对多、多对多的映射),延迟加载,查询缓存(一级缓存),二级缓存的学习记录;

1、学习中所使用到的例子,数据库基础分析

2、高级结果映射

3、延迟加载

4、一级缓存

5、二级缓存


1、学习中所使用到的例子,数据库基础分析


2、高级结果映射

resultType与resultMap:

  • resultType来进行结果映射,数据库中查询几条记录,那么在resultType就会映射成几条记录;resultType映射是一个平铺式的映射;
  • resultMap比较繁琐一些,是一种层级式映射,在企业中如果没有特殊要求,一般使用的都是resultType来完成一对一的映射;
  • resultType实现查询机制,需要自定义pojo,pojo属性名和sql查询的列名是一致的;企业开发中的resultType简单方便便于使用
  • resultMap可以将sql查询结果信息中的部分属性映射到一个pojo中;需要的是映射配置;并且如果有查询到其他表中的内容首先要进行的是实体类关系的分析,以及映射关系的分析,并且分清一对一,一对多,多对多的关系;

下面的例子中会使用上述的购物车的数据库结构创建表,并且生成实体po类,进行操作(代码只会贴出关键代码块);

例子1:订单信息与用户信息


使用实体PO类:

OrderCustom.java

package com.mybatis.demo.po;

/**
 * 继承一个需要信息最多的类
 * @author YQ
 *
 */
public class OrderCustom extends Orders {
    // 用户名称
    private String username;
    // 用户地址
    private String address;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

resultType的使用

<!-- 需要使用resultType实现订单查询,关联用户信息 -->
    <!--
        resultType必须要包含所有的查询结果类
        自定义POJO类
    -->
    <select id="findOrderUserList" resultType="com.mybatis.demo.po.OrderCustom">
        SELECT orders.* , user.username , user.address
        FROM orders , USER WHERE orders.user_id = user.id
    </select>

使用resultMap完成例子一中的需求:

<!-- 定义订单信息与用户信息的resultMap -->
    <!-- 将结果做一个映射 -->
    <resultMap type="orders" id="ordersUserResultMap">
        <!--
            id:订单信息的唯一约束
            如果存在多个字段决定唯一记录,id标签需要定义多个
        -->
        <id column="id" property="id"/>
        <result column="order_number" property="order_number"/>
        <result column="user_id" property="user_id"/>

        <!--
            配置用户映射信息
            将sql查询的用户信息映射到orders中的user属性中
            association:用于单个关联对象的映射
            property:将关联信息映射到orders的哪一个属性
            javaType:映射属性的类型
        -->
        <association property="user" javaType="com.mybatis.demo.po.User">
            <!--
                id:关联用户信息的唯一约束
                property:id指定的列映射到关联com.mybatis.demo.po.User
            -->
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>

使用resultMap

<select id="findOrderUserListResultMap" resultMap="ordersUserResultMap">
        SELECT orders.* , user.username , user.address
        FROM orders , USER WHERE orders.user_id = user.id
</select>

例子2:订单与订单明细查询


resultMap定义如下:

<!--
        定义订单以及订单明细的resultMap
        如果是跨namespace就可以在前面加上namespace
    -->
    <resultMap type="orders" id="ordersUserDetailResultMap" extends="ordersUserResultMap">
        <!-- 订单以及用户信息,继承于ordersUserResultMap -->

        <!--
            映射订单明细信息
            colllection:映射集合对象(表示的是多的关系)
            property:将明细信息映射到哪个集合属性中
            ofType:集合中对象的类型
        -->     

        <collection property="orderdetails" ofType="com.mybatis.demo.po.Orderdetail">
            <!--
                id:订单明细的唯一约束
            -->
            <id column="orderdetail_id" property="id"/>
            <result column="item_id" property="item_id"/>
            <result column="item_num" property="item_num"/>
            <result column="item_price" property="item_price"/>
        </collection>

    </resultMap>

在Orders类中需要定义一个订单明细的集合对象:

    //订单明细,需要给出该对象的get与set方法
    private List<Orderdetail> orderdetails;

使用定义的resultMap

<!-- 查询用户与订单明细信息 -->
    <select id="findOrdersUserDetailList" resultMap="ordersUserDetailResultMap">
        SELECT
            orders.*,
            user.username,
            user.address,
            orderdetail.item_id,
            orderdetail.item_num,
            orderdetail.item_price
        FROM
            orders,
            USER,
            orderdetail
        WHERE
            orders.user_id = user.id AND orders.id = orderdetail.orders_id
    </select>

例子3:订单明细与商品信息

<!-- 定义订单明细以及商品信息 -->
    <resultMap type="orders" id="ordersUserDetailItemResultMap"
        extends="ordersUserResultMap">
        <!-- 订单与用户信息,继承自ordersUserResultMap -->
        <!--
            映射订单信息collection:映射集合对象property;将明细信息映射到集合属性中!
            ofType:集合对象的类型
         -->
        <collection property="orderdetails" ofType="com.mybatis.demo.po.Orderdetail">
            <!--
                id:订单明细的唯一约束
            -->
            <id column="orderdetail_id" property="id"/>
            <result column="item_id" property="item_id"/>
            <result column="item_num" property="item_num"/>
            <result column="item_price" property="item_price"/>

            <!--
                映射商品信息
                映射商品属性
            -->
            <association property="items" javaType="com.mybatis.demo.po.Items">
                <id column="item_id" property="id"/>
                <result column="item_name" property="item_name"/>
                <result column="item_price" property="item_price"/>
                <result column="item_detail" property="item_detail"/>
            </association>

        </collection>
    </resultMap>

使用上述定义的resultMap

<!-- 查询订单以及订单明细信息以及商品信息 -->
    <select id="findOrderUserDetailItemList"
        resultMap="ordersUserDetailItemResultMap">
        SELECT
            orders.*,
            user.username,
            user.address,
            orderdetail.id orderdetail_id,
            orderdetail.item_id,
            orderdetail.item_num,
            orderdetail.item_price ,
            items.item_detail,
            items.item_name,
            items.item_price
        FROM
            orders,
            USER,
            orderdetail,
            items
        WHERE
            orders.user_id = user.id
        AND
            orders.id = orderdetail.orders_id
        AND
            orderdetail.item_id = items.id
    </select>

PO类中的定义:

在OrderDerail类中需要添加以下对象:

    //商品信息
    private Items items;//明细对应的商品信息 

3、延迟加载

  • 延迟加载对于上述例子中的需求:首次只查询订单信息,当需要关联查询用户信息时,再查询用户信息。
  • 延迟加载相对于之前学习的hibernate的概念就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息。Mybatis中resultMap可以实现延迟加载

在sqlMapConfig.xml中进行配置与开启:

    <!-- 全局参数的配置,开启延迟加载 -->
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 开启二级缓存总开关 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

在mapper中使用延迟加载:

<!-- 订单与用户的resultMap,实现延迟加载 -->
    <resultMap type="orders" id="ordersUserResultMapLazy">
        <!-- 配置订单信息的映射 -->
        <id column="id" property="id"/>
        <result column="user_id" property="user_id"/>
        <result column="order_number" property="order_number"/>
        <!--
            配置延迟加载,加载用户信息
            select:延迟加载时候调用的statement
            colum:将哪一列的值传到延迟加载的statement中
        -->
        <association property="user" javaType="com.mybatis.demo.po.User"
            select="com.mybatis.demo.mapper.UserMapper.findUserById" column="user_id">
            <id column="id" property="id"/>
        </association>
    </resultMap>

    <!-- 订单信息查询,需要使用延迟加载 -->
    <select id="findOrderList" resultMap="ordersUserResultMapLazy">
        select * from orders
    </select>

调试效果如下:

首先调试测试方法:

//测试延迟加载
@Test
    public void findOrderList() throws Exception {
        SqlSession session = sqlSessionFactory.openSession();
        OrdersMapperCustom orderMapperCustom = session.getMapper(OrdersMapperCustom.class);
        List<Orders> list = orderMapperCustom.findOrderList();

        for (Orders orders : list) {
            @SuppressWarnings("unused")
            int order_id = orders.getId();  //去订单ID;断点1
            @SuppressWarnings("unused")
            User user = orders.getUser();   //查询用户信息;断点2
        }
        session.close();
    }

4、一级缓存

首先先看一下一级缓存与二级缓存在mybatis中的关系:

  • 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
  • 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

一级缓存原理:

第一次查询id为X的用户,此时先去一级缓存查找,如果查找不到,则去数据库查询,把查询后的 结果存储到一级缓存中;

第二次查询id为X的用户,此时先去一级缓存查找,如果查找到,则直接从一级缓存中把数据取出,不去查询数据库;

只要中间发生增删改操作,那么一级缓存就清空;


5、二级缓存

  • 原理

    • 第一次查询id为1 的用户,此时先去二级缓存查找,如果查找不到,则去数据库查询,把查询后的 结果存储到二级缓存中。
    • 第二次查询id为1 的用户,此时先去二级缓存查找,如果查找到,则直接从二级缓存中把数据取出,不去查询数据库。
    • 只要中间发生增删改操作,那么二级缓存就清空。
    • 二级缓存默认是不开启的。

步骤一:开启二级缓存:

在sqlMapConfig.xml中开启二级缓存总开关:

<!-- 开启二级缓存总开关 -->
<setting name="cacheEnabled" value="true"/>

步骤二:开启二级缓存:

<!-- 开启二级缓存 -->
<cache></cache>

步骤三:对象序列化(必须)

implements Serializable

步骤四:测试即可


如何刷新缓存

  • 在映射文件的statement中设置flushCache=true可以刷新当前的二级缓存,默认情况下如果是select语句,那么flushCache是false。如果是insert、update、delete语句,那么flushCache是true;
  • 如果查询语句设置成true,那么每次查询都是去数据库查询,即意味着该查询的二级缓存失效;
  • 如果查询语句设置成false,即使用二级缓存,那么如果在数据库中修改了数据,而缓存数据还是原来的,这个时候就会出现脏读。

禁用缓存

<select id="findUserById" parameterType="int" resultType="user" useCache="false">
        SELECT * FROM USER WHERE id = #{id}
    </select>
时间: 2024-10-18 21:16:37

MyBatis结果映射与MyBatis缓存初探学习记录的相关文章

H5缓存机制学习记录

参考文章:http://mp.weixin.qq.com/s?__biz=MTEwNTM0ODI0MQ==&mid=404724239&idx=1&sn=e0a2887f9ff6293f0f550fa4e44057a0&scene=1&srcid=0331jLkF55dKeJO00POMiXLZ 1.浏览器缓存机制 2.Dom Storage(local storage 和 session storage) 3.Web SQL Database,不推荐使用. 根据官

MyBatis 学习记录5 MyBatis的二级缓存

主题 之前学习了一下MyBatis的一级缓存,主要涉及到BaseExecutor这个类. 现在准备学习记录下MyBatis二级缓存. 配置二级缓存与初始化发生的事情 首先二级缓存默认是不开启的,需要自己配置开启. 如上图,需要在configuration里去开启. 其次在需要用到二级缓存的Mapper的配置里做一些操作,如下图,增加一个cache节点 至此就可以在UserMapper上开启二级缓存了. 当MaBatis初始化的时候,需要解析各种XML配置来生成SQLSessionFactory,

mybatis初级映射

一 前言 系统学习知识请认准知识追寻者(同公众号),错过作者,你有可能要走好多弯路 经过第一篇的入门文章,小白们都对mybatis的搭建流程应该都很熟悉,这篇文章主讲的是如何使用mybatis实现数据库的增删改查,以及相关的标签属性.配置说明,可以说这篇文章是为你以后的学习和工作打下坚实基础文章,小白们要认真看,认真敲,下面是准备的sql语句.此文强到没朋友!!!! CREATE TABLE `course` ( `courseName` varchar(255) DEFAULT NULL CO

Mybatis高级映射

<select id="selectBlog_by_id" parameterType="int" resultMap="Blog_result"> select b.id, b.title, b.author_id, a.id, a.username, a.password, a.email, a.bio from Blog b left join Author a on b.author_id = a.id where b.id

SpringMVC + MyBatis + Mysql + Redis(作为二级缓存) 配置

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 整体思路 pomxml中加入Maven依赖 引入applicationContextxml中引入redis配置 创建缓存实现类RedisCache 创建中间类RedisCacheTransfer完成RedisCachejedisConnectionFactory的静态注入 配置文件redisproperties mapper中加入MyBatis二级缓存 Mybatis全局配置 打印Sql日志方便测试 测试代码 项目环境: 在

Mybatis源码学习记录

一.对源码先上一个结构图: 源代码主要在org.apache.ibatis目录下,18个包,其中在应用中主要的包有:builder.session.cache.type.transaction.datasource.jdbc.mapping,提供支撑服务的包有annotation.binding.io.logging.plugin.reflection.scripting.exception.executor.parsing 二.从使用入手 MyBatis使用的三板斧是SqlSessionFac

MyBatis开发学习记录

使用MyBatis时主要是完成POJO和SQL的映射规则 MyBatis基本构成: SqlSessionFactoryBuilder SqlSessionFactory SqlSession SqlMapper(主要是定义参数类型,描述缓存,描述SQL语句,定义查询结果和POJO的映射关系) 配置(<configuration>): <properties/> 在<properties>中可以定义参数如数据库密码,用户名等形式如: <properties>

SpringMVC +Spring + MyBatis + Mysql + Redis(作为二级缓存) 配置

转载:http://blog.csdn.net/xiadi934/article/details/50786293 项目环境: 在SpringMVC +Spring + MyBatis + MySQL.Redis部署在Linux虚拟机. 1.整体思路 参考Ehcache实现MyBatis二级缓存代码(Maven引用对应jar查阅) 使用Spring管理Redis连接池 模仿EhcacheCache,实现RedisCache 2.pom.xml中加入Maven依赖 1 <!-- spring-re

(十一)mybatis之映射器(select)

映射器 映射器的主要元素有八种: 元素名称 描述 select 查询语句,可自定义参数 insert 插入语句,执行后返回插入的条数 update 更新语句,执行后返回更新的条数 delete 删除语句,执行后返回删除的条数 sql 定义一部分的sql,被各处引用 resultMap 描述从数据库中得到的结果,提供映射规则 cache 给定命名空间的缓存配置 cache-ref 其他命名空间缓存配置的引用   select元素 ①   简单地应用查询的select元素: <select id =