Mybatis学习记录
1.Mybatis简要概述
1.1 什么是Mybatis
(1)MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.2 什么是持久层
(1)持久层就是数据持久化:持久化就是将程序的数据在持久状态和瞬时状态转化的过程
(2)完成持久化工作的代码块
2.配置详解
2.1 环境配置(environments)
(1)MyBatis 可以配置成适应多种环境,不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。即每个数据库对应一个SqlSessionFactory 实例
1.<environments id =“development”>:
1. id = development 默认使用的环境ID
2.<development id=“development”>:
1. id = "development" 环境ID
3.<transactionManager type=“JDBC”>
1. 在 MyBatis 中有两种类型的事务管理器 JDBC/MANAGED.
2. i.JDBC:这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
3. ii.MANAGED:这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期
4. Mybatis默认使用的是JDBC
4.<dataSource type=“POOLED”>
a)dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
b)有三种内建的数据源类型UNPOOLED POOLED JNDI
PS:Mybatis连接池默认使用的是POOLED
PS:<dataSource type=“POOLED”>下面的就是你的数据库连接信息了
2.2 属性(properties)
PS:在外部创建一个xxx.properties文件,输入一下信息
PS:引入外部的xx.properties文件
- 这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
2.3 类型别名(typeAliases)
- 给实体类全类路径起别名
- 给包起别名
PS:给包起别名如果不去实体类使用注解的话,默认别名为该实体类的首字母小写(比如UserName实体类即为userName)
2.4 设置(Settings)
(1)这个可前往官网查看:https://mybatis.org/mybatis-3/zh/configuration.html#settings
2.5 映射器(mappers)
- MapperRegistry:注册绑定我们的Mapper文件
- 绑定方式1:
- 绑定方式2:
- 绑定方式3:
PS:映射文件与dao层的接口名字需一致,不然报如下错误
3.生命周期和作用域
3.1 SqlSessionFactoryBuilder
① 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了
② 因此SqlSessionFactoryBuilder实例的最佳作用域是方法作用域。即局部方法变量
3.2 SqlSessionFactory
①SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。它不需要多次创建。
②因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式
3.3 SqlSession
①每个线程都应该有它自己的 SqlSession 实例。
②SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
③因此,我们需要在每次用完之后,赶紧关闭,否者资源会被占用。
4.resultMap(结果集映射)
4.1 问题演示
(1) 问题:当数据库字段跟实体类字段不一致时,就会出现获取到的内容为null的情况
(2) 解决:采用resultMap结果集映射–如下
其实这个只要将字段不一样的去映射就可以了,不必要一样的还去映射一遍(如下)
5.日志
5.1 开启日志等演示
(1)怎么开启日志:在mybatis核心配置文件开启
(2)开启Log4j日志工厂
①需要先导入log4j的jar包
②去mybatis核心配置文件设置
③创建一个log4j.properties文件
④PS:日志对象,参数为当前类的class。日志对象的创建及用处如下图
6.分页
6.1 利用sql语句limit进行分页
PS:先写好一个sql语句
PS:接口定义好,使用万能的map来传参数
PS:编写测试类
7.使用注解开发
7.1 使用java注解(编写查询)
PS:在dao层接口方法上注解输入sql语句
PS:使用class文件注册绑定映射
PS:其它sql操作万变不离其宗。
PS:不想要每次增删改都手动提交,可以改 如图
8.多对一的处理(association:关联)
8.1 按照结果嵌套处理
PS:Student类
PS:Mapper.xml的查询语句编写
8.2 按照查询嵌套处理: 即子查询
PS:Student实体类上方有,就不贴出来了,直接上xml配置
9.一对多的处理(collection:集合)
9.1 按照结果嵌套处理
PS:Teacher实体类
PS:Mapper.xml查询语句编写
9.2 按照查询嵌套处理: 即子查询
PS:实体类上面有了,就不重复了,Mapper.xml编写
9.3 总结一下多对一与一对多
(1) 关联使用:association(多对一)
(2) 集合使用:collection(一对多)
(3) javaType和ofType
1)javaType用来指定实体类中属性的类型
2)ofType用来指定映射到list或者集合中的实体类类型,即泛型中的约束类型
10.动态SQL
10.1 什么是动态SQL
(1)动态SQL就是根据不同的条件生成不同的SQL语句
10.2 动态SQL之IF
PS:接口方法
PS:SQL编写
PS:测试
10.3 动态SQL语句之choose when otherwise
PS:接口方法
PS:SQL编写
PS:测试代码
10.4 动态SQL之set
PS:接口方法
PS:SQL编写
PS:测试
PS:这里还有个重要的点(这是官网的说法,可以理解一下)mybatis官网
10.5 动态SQL之foreach
PS:接口方法
PS:SQL编写
PS:测试代码
10.6 SQL片段
(1)SQL片段就是,当我们发现有些部分可以复用的时候,我们使用SQL片段将可以复用的部分提取出来
11.缓存
11.1 什么是缓存
(1)存在内存中的临时数据
(2)将用户经常查询的数据放在缓存中,用户去查询数据就不用从磁盘上查询,而是从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题
11.2 为什么使用缓存
(1)减少和数据库的交互次数,减少系统开销,提高系统效率
(2)当我们经常查询但是不经常改变的数据,就可以使用缓存
11.3 一级缓存
(1)一级缓存也叫本地缓存
(2)与数据库同一次会话期间查询的数据会放到本地缓存中,以后要用到这些数据的时候直接从缓存中拿,不需要再去查询数据库。
(3)一级缓存结束于你关闭SqlSession的时候。
(4)测试一级缓存
(5)缓存失效的情况:
1)使用更新 插入 删除语句的时候,缓存会更新,即失效。
2)关闭连接也会失效
3)手动清理缓存
4)不同Mapper文件
11.4 二级缓存
1.二级缓存也叫全局缓存
2.基于namespace级别的缓存,一个名称空间对应一个二级缓存
3.工作机制
1)一个会话查询到一条数据,这个数据就会被放在当前会话的一级缓存中。
2)如果会话关闭了,这个会话的一级缓存就没了,但是我们想要的是,这个一级缓存关闭了,数据会保存到二级缓存中
3)新的会话查询信息,就可以从二级缓存中获取内容。
4)不同的mapper查处的数据会放在自己对应的缓存中
4.开启二级缓存步骤:
···4.1先去mybatis核心配置文件开启cacheEnabled(虽然它默认就是true)···
···4.2 在当前Mapper.xml中使用二级缓存···
···4.3 注意点:一般记得要序列化实体类···
PS:二级缓存注意点:二级缓存是在一级缓存关闭之后才会将数据放到二级缓存的
11.5 缓存的一个原理(执行顺序)
1.缓存的一个原理(执行顺序)
1. 先去二级缓存里查看是否有想要的数据,有就直接取
2. 二级缓存没有再去一级缓存里查看是否有,有就直接取
3. 如果一级缓存也没有,再去数据库查询,然后数据查询到的会放在一级缓存里,一级缓存关闭数据会放到二级缓存里去。大致就是这么个流程
12.自定义缓存
12.1 流程讲解
(1)首先老规矩先导包
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
(2)然后配置ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--
diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
user.home – 用户主目录
user.dir – 用户当前工作目录
java.io.tmpdir – 默认临时文件路径
-->
<diskStore path="java.io.tmpdir/Tmp_EhCache"/>
<!--
defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
-->
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统当机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
PS:结束,希望众位可以指出问题或者补充