Mybatis
-
- -
框架的好处框架是一个半成品,已经对基础的代码进行了封装并提供相应的 API,开发者在
使用框架是直接调用封装好的 API 可以省去很多代码编写,从而提高工作效率和开发速度
- 重用代码大大增加,软件生产效率和质量也得到了提高;
- 代码结构的规范化,降低程序员之间沟通以及日后维护的成本;
- 开发速度加快,开发人员减少,维护费用降低,
- 减少开发时间、降低开发难度
学习目标
掌握:
Mybatis的基本使用、Java 日志处理框架、Mybatis 配置完善 、SqlSession 常用 API 、Mapper 动态代理 、动态 SQL 、Mybatis 缓存 、Mybatis 多表关联查询、Mybatis 注解的使用 、Mybatis Generator 工具的使用、PageHelper 分页插件、Mybatis 与 Servlet 整合
ORM,Object-Relationl Mapping
MyBatis框架的优点和缺点
-
- -
对象关系映射,它的作用是在关系型数据库和对象之间作一个映射处理。项目中的业务实体有两种表现形式:对象和关系数据,即在内存中表现为对象,在数据库中表现为关系数据。
JDBC 的缺点:需要手动的完成面向对象的 Java 语言、面向关系的数据库之间数据的转换,代码繁琐,影响了开发效率。
ORM:在面向对象的java语言中,面向关系的数据库之间数据的转换是必须的,数据库中的数据是不能直接拿来使用,需要转换成需要的对象来使用,但是每次在开发时需要先建立数据库然后在对数据库中的数据转成我们可以操作的对象;因此ORM就相当于转换的桥梁,开发者不需要和sql语句打交道了。
ORM将数据库映射成对象
- 数据库的表(table) --> 类(class)
- 记录(record,行数据)--> 对象(object)
- 字段(field)--> 对象的属性(attribute)
Mybatis框架简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain OrdinaryJava Object,普通的 Java 对象)映射成数据库中的记录。MyBatis是一个半自动ORM框架,其本质是对JDBC的封装。使用MyBatis重点需要程序员编写 SQL 命令,不需要写一行 JDBC 代码。
持久层框架:优化了对数据库的访问速度,减少了对数据库中的访问频率,将数据库中的关系数据通过对象关系映射成对象,这时对象中的存放的就是数据库中的内容(如果需要执行则存放到内存中),当程序需要某一个对象的属性执行时,无需再从数据库中访问且做转换就可以获取。
与 Hibernate 的比较:
Hibernate 是一个全自动的 ORM 框架。因为 Hibernate 创建了 Java 对象和数据库表之间的完整映射,可以完全以面向对象的思想来操作数据库,程序员不需要手写 SQL 语句。而 MyBatis 中还需要手写 SQL 语句,所以是半自动化的,工作量要大于 Hibernate。为什么半自动化的 Mybatis 自动化的 Hibernate 受欢迎?
MyBatis 需要手写 SQL 语句,所以工作量要大于 Hibernate。但是也正是由于自定义SQL 语句,所以其灵活性、可优化性就超过了 Hibernate。MyBatis 将手写 SQL 语句的工作丢给开发者,可以更加精确的定义 SQL,更加灵活,
也便于优化性能。完成同样功能的两条 SQL 语句的性能可能相差十几倍到几十倍,在高并发、快响应要求下的互联网系统中,对性能的影响更明显。MyBatis 对存储过程可提供很好的支持。
Mybatis 的 jar 包介绍
- asm-7.1.jar :字节码修改框架
- javassist-3.27.0-GA.jar: 可用来检查、”动态”修改及创建 Java 类。功能与 JDK 自带反射功能类似,但比反射功能更强大
- cglib-3.3.0.jar :实现动态代理的技术,延迟加载时使用
- ognl-3.2.14.jar :对象导航图语言的缩写,功能强大的表达式语言工具包。在动态 SQL 和${param}中使用
- commons-logging-1.2.jar: 日志包
- slf4j-api-1.7.30.jar: 日志包
- slf4j-log4j12-1.7.30.jar: 日志包
- log4j-1.2.17.jar: 日志包
- log4j-api-2.13.3.jar :日志包
- log4j-core-2.13.3.jar: 日志包
核心API
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的作用是用来创建 SqlSessionFactory 对象。当 SqlSessionFactory 对象被创建后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域。
SqlSessionFactory
可以被认为是一个数据库连接池,它的作用是创建 SqlSession接口对象。一旦创建了SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。由于 SqlSessionFactory是 一 个 对 数 据 库 的 连 接 池 , 所 以 它 占 据 着 数 据 库 的 连 接 资 源 。 如 果 创 建 多 个SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。因此 SqlSessionFactory 是一个单例,让它在应用中被共享。
SqlSession
如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的commit、rollback 方法提交或者回滚事务。SqlSession 应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try...catch...finally... 语句来保证其正确关闭
Mapper
映射器。由一个 Java 接口和 XML 文件(或者注解构成),需要给出对应的 SQL 和映射规则,负责发送 SQL 去执行并返回结果。由于 SqlSession 的关闭,它的数据库连接资源也会消失,所以它的生命周期应该小于等于 SqlSession 的生命周期。Mapper 代表的是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它。
Mybatis的配置文件
全局配置文件和映射配置文件:如果说全局配置闻不见是连接数据库的配置已经环境的设置,那么映射配置文件就是编写sql语句的(JDBC是将sql语句和代码写在一起然后进行CRUD,Mybatis则是进行了节偶,是功能代码具有可用性,开发简单。
-
- -
全局配置文件
全局配置文件的名称是自定义的,在 JavaProject 项目中需要放到 src 目录下。全局配置文件的作用是完成一些全局性的配置,如:对 Mybatis 框架的设置、别名设置、环境设置、指定映射配置文件等相关配置。
-
- -
- properties 标签
properties 标签中允许内部定义属性,也可以是外部的properties 文件定义属性。无论是内部定义还是外部定义,都可以使用${name}获取值。
配置文件中内部定义
配置文件中外部定义
-
- -
- settings 标签
setting 标签的配置是配置 MyBatis 框架运行时的一些行为的,例如缓存、延迟加载、结果集控制、执行器、分页设置、命名规则等一系列控制性参数,其所有的 setting 配置都放在父标签 settings 标签中(也可以不用配置)。
-
- -
- typeAliases 标签
类型别名可为 Java 类型设置一个缩写名字。
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
-
- -
- environments 标签
配置连接数据库的环境,可以配置多个环境,比如:开发、测试、发布产品的环境
transactionManager 节点
事务处理器。在Mybatis中有两种事务管理器,也就是type = JDBC或type = MANAGED
- JDBC:这个配置直接使用了 JDBC 的提交和回滚事务,它依赖从数据源获得的连接来管理事务作用域
- MANAGED:在Mybatis中不做事务处理,在JavaEE开发的标准中根据开发框架获取事务
-
- -
- dataSource 标签
配置数据连接源(JDBC连接对象的资源,获取数据连接池)
- UNPOOLED:使用直连
- POOLED:使用池连
- JNDI:使用JNDI方法连接
-
- -
- mapper 标签
指定映射配置文件
使用相对类路径指定映射配置文件
使用 filter:///协议指定映射配置文件
指定映射接口
通过包名指定映射接口(指定映射文件)
-
- -
映射配置文件
映射配置文件主要是用来编写 sql 语句的,结果集的映射关系的指定,以及缓存的一些配置等等。
- namespace
mybatis中可以为每个映射文件起一个唯一的命名空间(namespace),只要这个命名空间的id是唯一,即使不同的映射文件的sql语句id一样也不会产生冲突
-
- -
- resultMap 标签
指定查询结果集与对象的映射关系的标签
type:类的完全名, 或者一个类型别名,可以理解为数据库中的表转换成了一个对象,该对象里面的属性即使数据库中表的字段名称,CRUD该表时,将字段对应的数据填充到改对象中。
id:唯一标识。在进行业务处理时,该标签指定程序获取执行sql语句,在一个映射文件中是唯一的
- id 标签
指定主键中的值,用于标识一个结果映射。
property: 该属性值相当于在操作sql语句时起的别名
- select、insert、updata、delete标签
parameterType:指定参数类型。该属性是可选属性。因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数。
resultType:期望从这条语句中返回结果的类全名或别名。
resultMap:使用 resultMap 标签来处理结果集映射。
Mybatis案例
添加DTD约束文件
在没有联网的情况下,如果让 dtd 约束继续起作用,并且出现标签提示,可以通过引入本地 dtd 文件来实现,将下载的 dtd 拷贝到本地的一个目录下
Idea 操作路径:File---Settings---Languages & Frameworks。其中 URI 复制 dtd 的网络地址即可。File 选择 dtd 文件在本地的地址
注意:在 MyBatis 的核心 jar 包中就提供了 mybatis-3-config.dtd
添加 jar 包
创建实体
public class Users {
private int userid;
private String username;
private String usresex;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsresex() {
return usresex;
}
public void setUsresex(String usresex) {
this.usresex = usresex;
}
}
创建 properties 文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=root
创建全局配置文件
在这里使用了外部定义的properties属性
创建映射配置文件
创建 UsersDao 接口
public interface UsersDao {
List selectUsersAll()throws IOException;
}
创建 UsersDao 接口实现类
public class UsersDaoImpl implements UsersDao {
/**
* 查询所有用户
* @return
*/
@Override
public List selectUsersAll()throws IOException {
// 创建 SqlSessionFactory 对象
InputStream inputStream = Resources.getResourceAsStream("mybatis-cfg.xml");
SqlSessionFactory sqlSessionFacotry = new SqlSessionFactoryBuilder().build(inputStream);
// 获取 SqlSession 对象
SqlSession sqlSession = sqlSessionFacotry.openSession();
// 通过 SqlSession 对象下的 API 完成对数据库的操作
List list = sqlSession.selectList("com.bjsxt.mapper.UserMapper.selectUsersAll");
// 关闭 SqlSession 对象
sqlSession.close();
return list;
}
}
Mybatis 中的参数绑定
在映射配置文件中向 SQL 语句中绑定参数的语法结构为#{ }和${ }。
#{}和${}的区别(面)
#{ }: 解析为一个 JDBC 预编译语句(PreparedStatement)的参数标记符占位符 ?。使
用该方式可避免 SQL 注入
${ }: 仅仅为一个纯碎的 String 替换,在 Mybatis 的动态 SQL 解析阶段将会进行变量替
换。${ } 在预编译之前已经被变量替换了,这会存在 SQL 注入问题。
Mybatis工具类
ThreadLocal 介绍
ThreadLocal 提供了线程内存储变量的能力,这些变量不同之处在于每一个线程读取的变量是对应的互相独立的。通过 get 和 set 方法就可以得到当前线程对应的值
使用 ThreadLocal 存储 SqlSession
如果多个 DML 操作属于一个事务,因为 commit()和 rollback()都是由 SqlSession 完成的,所以必须保证使用一个 SqlSession。但是多个不同的 DML 操作可能在不同类的不同方法中,每个方法中要单独的获取 SqlSession。比如商城下订单时,其实涉及商品库存变化、订单添加、订单明细添加、付款、日志添加等多个 DML 操作,分布在不同类中。如何在多个 DML 操作之间使用同一个 SqlSession 呢,可以使用 ThreadLocal 来存储。保证一个线程中的操作使用的都是一个 SqlSession。
在 Web 项目中用户的每次请求会启动一个新的线程,比如点击”结算”完成购物车结算。在 Java 项目中每次启动 main()也会自动开启一个 main 线程
public class MybatisUtils {
private static ThreadLocal threadLocal = new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory = null;
static{
// 创建 SqlSessionFactory
InputStream is = null;
try{
is = Resources.getResourceAsStream("mybatis-cfg.xml");
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
// 获取 SqlSession
public static SqlSession getSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
// 关闭 SqlSession
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession != null){
sqlSession.close();
threadLocal.set(null);
}
}
}
Mybatis 的事务提交方式
在 Mybatis 中事务提交方式默认为手动提交,这与 JDBC 是不同的。在 JDBC 中事务默认提交方式为自动提交。
- 手动提交事务(默认)
SqlSession sqlSession = sqlSessionFacotry.openSession();
- 自动提交事务
SqlSession sqlSession = sqlSessionFacotry.openSession(true);
Java日志处理框架
常用日志处理框架
- Log4j: Log For Java(Java 的日志) 是 Apache 提供的一个开源的 Java 主流的日志框架。
- Log4j2:
Log4j 定义了 8 个日志级别(除去 OFF 和 ALL,可以说分为 6 个级别),优先级从高到
低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
在 Log4j 中建议只使用 DEBUG、INFO、WARN、ERROR 四个日志级别
* **ALL** 最低等级的,用于打开所有日志记录。
* **TRACE** designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的
日志级别,一般不会使用。
* **DEBUG** 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
* **INFO** 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志
* WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一
些提示。
* ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,
如果不想输出太多的日志,可以使用这个级别。
* FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错
误,这种级别你可以直接停止程序了。
* OFF 最高等级的,用于关闭所有日志记录。
- Commons
- Logging,
- Slf4j,
- Logback,
- Jul。
Log4j 的使用
- Log4j 配置文件名:log4j 配置文件名:log4j.properties,Log4j 配值文件存放位置:项目的 src 的根目录中
- 配置根 Logger:
log4j.rootLogger = [level],appenderName,appenderName2,...
level 是日志记录的优先级,优先级从低到高分别是 DEBUG,INFO,WARN,ERROR。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关,比如在这里定义了INFO 级别,则应用程序中所有 DEBUG 级别的日志信息将不被打印出来appenderName 就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。
- Log4j 中的 appender
org.apache.log4j.ConsoleAppender(输出到控制台)
org.apache.log4j.FileAppender(输出到文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
org.apache.log4j.jdbc.JDBCAppender(将日志信息添加数据库中)
- 向控制台输出的 appender
# appender.console 输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=<%d> %5p (%F:%L) [%t] (%c)- %m%n
log4j.appender.console.Target=System.out
- 向文件输出的 appender
### appender.logfile 输出到日志文件 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=SysLog.log
log4j.appender.logfile.MaxFileSize=500KB
log4j.appender.logfile.MaxBackupIndex=7
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=<%d> %p (%F:%L) [%t] %c - %m%n
- 向数据库输出的 appender
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/bjsxt
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=root
log4j.appender.logDB.Sql=INSERT INTO
logs(project_name,create_date,level,category,file_name,thread_name,line,all_
category,message)values('logDemo','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
- 通过包名控制日志输出级别
log4j.logger.org.apache=FATAL
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.springframework=ERROR
log4j.logger.com.bjsxt=ERROR
Mapper 动态代理
规范
- 接口名称需要与映射配置文件名称相同
- 映射配置文件中 namespace 必须是接口的全名。
- 接口中的方法名和映射配置文件中的标签的 id 一致。
- 接口中的返回值类型和映射配置文件中的 resultType 的指定的类型一致。
Mapper 动态代理模式下的多参数处理
顺序传参法
在映射文件中,SQL 语句中的参数需要使用 arg0,arg1...或者 param1,param2...表示参数的顺序。此方法可读性低,且要求参数的顺序不能出错,在开发中不建议使用
List selectUsersOrderParam(String username,String usersex); |
---|
@Param 注解传参法
在接口方法的参数列表中通过@Param 注解来定义参数名称,在 SQL 语句中通过注解中所定义的参数名称完成参数位置的指定。
此方式在参数不多的情况还是比较直观的,推荐使用。
List selectUsersAnnParam(@Param("name") String
username,@Param("sex") String usersex);
POJO 传参法
在 Mapper 动态代理中也可以使用 POJO 作为传递参数的载体,在 SQL 语句中绑定参数时使用 POJO 的属性名作为参数名即可。此方式推荐使用。
List selectUsersPOJOParam(Users users);
Map 传参法
在 Mapper 动态代理中也可以使用 Map 作为传递参数的载体,在 SQL 语句中绑定参数时使用 Map 的 Key 作为参数名即可。此方法适合在传递多参数时,如果没有 POJO 能与参数匹配,可以使用该方式传递参数。推荐使用。
MyBatis 传递 map 参数时,如果传递参数中没有对应的 key 值,在执行 sql 语句时默认取的是 null。
List selectUsersMapParam(Map map);
使用符号实体
我们可以使用符号的实体来表示
动态 SQL
-
- -
Mybatis动态sql有什么用?执行原理?有哪些动态sql?
-
- -
在 MyBatis 中提供了动态 SQL 功能。将使用 Java 代码拼接 SQL 语句,改变为在 XML 映射文件中使用标签拼接 SQL 语句。
MyBatis 中动态 SQL 是编写在 mapper.xml 中的,其语法和 JSTL 类似,但是却是基于强大的 OGNL 表达式实现的。
OGNL (对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在Struts2等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。)
- if 标签
if 标签单分支判断语句
- choose、when、otherwise 标签
从多个条件中选择一个使用。
- where 标签
使用 where 标签,就不需要提供 where 1=1 这样的条件了。如果判断条件不为空则自动添加 where 关键字,并且会自动去掉第一个条件前面的 and 或 or
- bind 标签
bind 标签允许我们在 OGNL 表达式以外创建一个变量,并可以将其绑定到当前的 SQL语句中。一般应用于模糊查询,通过 bind 绑定通配符和查询值。
- set 标签
set 标签用在 update 语句中。借助 if 标签,可以只对有具体值的字段进行更新。set 标签会自动添加 set 关键字,自动去掉最后一个 if 语句的多余的逗号。
update users
username = #{username},
usersex = #{usersex},
where userid = #{userid}
- foreach 标签
foreach 标签的功能非常强大,我们可以将任何可迭代对象如 List、Set 、Map 或者数组对象作为集合参数传递给 foreach 标签进行遍历。它也允许我们指定开头与结尾的字符串以及集合项迭代之间的分隔符。
迭代 List、Set
迭代数组
Mybatis 缓存
在执行了一次SQL查询语句时,查询结果存储在内存或者某种缓存介质(Mybatis的缓存介质有哪些)当中,当下次遇到相同的查询 SQL 时候不在执行该 SQL,而是直接从缓存中获取结果
MyBatis 缓存方式分为一级缓存和二级缓存,同时也可配置关于缓存设置。
一级缓存是将结果缓存在 SqlSession 对象中,二级缓存是存储在 SqlSessionFactory 对象中。默认情况下,MyBatis 开启一级缓存,没有开启二级缓存。当数据量大的时候可以借助一些第三方缓存技术来协助保存 Mybatis 的二级缓存数据。
一级缓存的使用
一级缓存也叫本地缓存,MyBatis 的一级缓存是在会话(SqlSession)层面进行缓存的。在SqlSession中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的SqlSession之间的缓存数据区域(HashMap)是互相不影响的;MyBatis 的一级缓存是默认开启的,不需要任何的配置。
一级缓存的生命周期
- MyBatis 在开启一个数据库会话时,会创建一个新的 SqlSession 对象,SqlSession 对象中会有一个新的 Executor (Executor是什么?)对象。Executor 对象中持有一个新的PerpetualCache(PerpetualCache是什么?) 对象;当会话结束时,SqlSession 对象及其内部的 Executor 对象还有 PerpetualCache 对象也一并释放掉。
- 如果 SqlSession 调用了 close()方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存
将不可用。
- 如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象中的数据,但是该对象
仍可使用。
- 如果中间(半路中)sqlSession去执行commit操作(update()、delete()、insert()) ,都会清空SqlSession中的数据,这样做的目的是更新缓存中的数据(PerpetualCache 对象),避免脏读
-
- -
如何判断两次查询是完全相同的查询?
Mybatis 认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询。
- 传入的 statementId(statementId是什么?)。
- 查询时要求的结果集中的结果范围。
- 这次查询所产生的最终要传递给 PreparedStatement 的 Sql 语句字符串。
- 传递的参数值
二级缓存的使用
MyBatis 的二级缓存是 Application 级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。二级缓存是 SqlSessionFactory 上的缓存,可以是由一个 SqlSessionFactory 创建的不同的 SqlSession 之间共享缓存数据。默认并不开启。SqlSession 在执行 commit()或者 close()的时候将数据放入到二级缓存。
SqlSession 共享二级缓存
二级缓存的配置方式
二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis 要求缓存的 POJO 必须是可序列化的, 也就是要求实现 Serializable 接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中。在映射配置文件中配置就可以开启缓存了。
二级缓存特点
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 二级缓存是以 namespace(全局命名空间) 为单位的,不同 namespace 下的操作互不影响
- 如果在加入标签的前提下让个别 select 元素不使用缓存,可以使用 useCache
属性,设置为 false。
- 缓存会使用默认的 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表,比如 No Flush Interval,(CNFI 没有刷新间隔),缓存不会以任何时间顺序
来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改。
-
- -
Mybatis 注解的使用
在 Mybatis 中如果使用注解式开发,那么注解需要添加在 Mapper 接口中的抽象方法上,在注解中给定需要执行的 SQL 语句即可,这样就可以不需要映射配置文件。MyBatis 支持纯注解方式,支持纯映射配置文件方式,也支持注解和映射配置文件混合形式。当只有接口没有映射配置文件时在 mybatis-cfg.xml 中对于引入映射可以通过加载指定接口类。也可以使用指定加载的包。
实例
- 使用注解完成查询
@Select("select * from users")
List selectUsersAll();
注解式开发时的参数传递
顺序传参法
@Select("select * from users where username = #{param1} and usersex= #{param2}")
List selectUsersByNameAndSexOrder(String username,String usersex);
@Select("select * from users where username = #{name} and usersex = #{sex}")
List selectUsersByNameAndSexOrder2(@Param("name") String username,@Param("sex") String usersex);
POJO 传参法
#{}里面的参数名称要与实体类的属性名称一致
@Select("select * from users where username = #{username} and usersex = #{usersex}")
List selectUsersByNameAndSexPOJO(Users users);
Map 传参法
当key不存在时,则返回null
@Select("select * from users where username = #{keyname} and usersex = #{keysex}")
List selectUsersByNameAndSexMap(Map map);
OpenSessionInView 的使用
什么是 Open Session In View
Open Session In View 模式:
Open Session In View 是将一个数据库会话对象绑定到当前请求线程中,在请求期间一直保持数据库会话对象处于 Open 状态,使数据库会话对象在请求的整个期间都可以使用。直到产生响应后关闭当前的数据库会话对象