Mysql

MyBatis

配置解析

核心配置文件

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

  • configuration(配置)

    • properties(属性)

    • settings(设置)

    • typeAliases(类型别名)

      • 设置短的名字

      • 意义:减少代码冗余

      • 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
        
        <typeAliases>
          <typeAlias alias="Author" type="domain.blog.Author"/>
          <typeAlias alias="Blog" type="domain.blog.Blog"/>
          <typeAlias alias="Comment" type="domain.blog.Comment"/>
          <typeAlias alias="Post" type="domain.blog.Post"/>
          <typeAlias alias="Section" type="domain.blog.Section"/>
          <typeAlias alias="Tag" type="domain.blog.Tag"/>
        </typeAliases>
        当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。
        
        也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
        
        <typeAliases>
          <package name="domain.blog"/>
        </typeAliases>
        
        

        每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:
        必须是在扫描包的情况下

        @Alias("author")
        public class Author {
            ...
        } 
        
    • typeHandlers(类型处理器)

    • objectFactory(对象工厂)

    • plugins(插件)

    • environments(环境配置)

      • environment(环境变量)
        • transactionManager(事务管理器)
        • dataSource(数据源)
    • databaseIdProvider(数据库厂商标识)

    • mappers(映射器)

{}

${}预编译

动态SQL

什么是动态SQl

动态SQL根据不同的条件生成不同SQL语句

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

if
choose (when, otherwise)
trim (where, set)
foreach

搭建环境

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT '博客id',
  `title` varchar(100) NOT NULL COMMENT '博客标题',
  `author` varchar(30) NOT NULL COMMENT '博客作者',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Mybatis流程

1、导包

2、编写配置文件 mybatisconfig.xml

3、编写实体类

4、编写实体类对应Mapper接口和Mapper.xml文件

IF指令

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from mybatis.blog where 1=1
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</select>

Where标签

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

choose (when, otherwise)指令

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

遇见第一个符合条件的就走那一条sql语句

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>              
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

set语句

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

或者,你可以通过使用trim元素来达到同样的效果:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

SQL片段

有的时候我们会将公共部分抽取出来,方便复用

1.使用SQL标签抽取公共部分

//SQL标签
<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        title = #{author}
    </if>
</sql>

2.在需要使用的地方使用include标签引用即可

<!--查询,通过传入的参数来判断-->
<select id="queryBlogIF2" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <include refid="if-title-author"></include>
    </where>
</select>

注意事项:

  • 最好基于单表来定义SQL片段!
  • 不要存在where标签(SQL标签为了复用,里面嵌套where没什么用)

Foreach指令

image-20230529184506821

<!--
        select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)
        我们现在传递一个万能的map , 这map中可以存在一个集合!
-->
<select id="queryBlogForeach" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <where>
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id = #{id}
        </foreach>
    </where>
</select>

缓存

查询  :  连接数据库 ,耗资源!
	一次查询的结果,给他暂存在一个可以直接取到的地方!--> 内存 : 缓存

我们再次查询相同数据的时候,直接走缓存,就不用走数据库了
  1. 什么是缓存 [ Cache ]?
    • 存在内存中的临时数据。
    • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题
  2. 为什么使用缓存?
    • 减少和数据库的交互次数,减少系统开销,提高系统效率。
  3. 什么样的数据能使用缓存?
    • 经常查询并且不经常改变的数据。【可以使用缓存】

主从赋值

一级缓存(默认开启,只在一次会话有效)

  1. 一级缓存又叫本地缓存:

    • 与数据库同一次会话期间查询到的数据会放在本地缓存中。

    • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库

    • 缓存失效的情况:

      1.查询不同的东西

      1. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存!

      image-202305300021156713.查询不同的Mapper.xml

      4.手动清理缓存!

      sqlSession.clearCache()手动清除缓存
      

二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
    • 新的会话查询信息,就可以从二级缓存中获取内容
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中

步骤:

  1. 开启全局缓存

    <!--显示的开启全局缓存-->
    <setting name="cacheEnabled" value="true"/>
    

2.在要使用二级缓存的Mapper中开启

<!--在当前Mapper.xml中使用二级缓存-->
<cache/>

3、也可以自定义参数

<!--在当前Mapper.xml中使用二级缓存-->
<cache  
   eviction="FIFO"
   flushInterval="60000"
   size="512"
   readOnly="true"/>

测试

  1. 问题:我们需要将实体类序列化!否则就会报错!

    Caused by: java.io.NotSerializableException: com.kuang.pojo.User
    

    在实体类继承Serializable接口即可

小结:

  • 只要开启了二级缓存,在同一个Mapper下就有效
  • 所有的数据都会先放在一级缓存中
  • 只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!

缓存原理

img

自定义缓存-Ehcache

Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存

导入依赖

<dependencies>
  ...
  <dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.3</version>
  </dependency>
  ...
</dependencies>

在mapper中指定使用我们的ehcache缓存实现!

<!--在当前Mapper.xml中使用二级缓存-->
可以自定义缓存也可以使用第三方远程
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

Limit实现分页

使用Mybatis实现分页,核心SQL

Limit需要注意:

如果只给定一个参数的话,就是从0查询到这个位置上。

  1. 接口

    //分页
    List<User> getUserByLimit(Map<String,Integer> map);
    
  2. Mapper.xml

    <!--/分页-->
    <select id="getUserByLimit" parameterType="map" resultMap="UserMap">
        select * from  mybatis.user limit #{startIndex},#{pageSize}
    </select>
    
  3. 测试

    @Test
    public void getUserByLimit(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
    HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",1);
        map.put("pageSize",2);
    
        List<User> userList =  mapper.getUserByLimit(map);
        for (User user : userList) {
        System.out.println(user);
        }
    
        sqlSession.close();
        }
    

mybatis执行流程

img

img

并且SqlSession有开启事务处理

image-20230530164035040

posted @ 2023-12-17 23:53  zL66  阅读(2)  评论(0编辑  收藏  举报