MyBatis
# 目录
- 阅读官方文档或相关教程,了解 MyBatis 的基本概念和作用。理解 MyBatis 是如何简化 JDBC 编程的。
- 了解 MyBatis 的 XML 配置方式,学习如何配置数据源、SQL 映射等。
- 学习如何使用注解来进行持久层操作,而不是依赖于 XML 文件进行配置。
- 学会快速搭建 MyBatis 环境,接入现有项目中
- 理解
SqlSessionFactory
的执行过程
# 介绍
# 官网介绍
官网:https://mybatis.org/mybatis-3/zh/index.html
- MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github
- MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发
- MyBatis 出现是为了解决连接持久层的时候,出现很多硬编码以及 SQL 语句维护的问题。使用MyBatis 对持久层进行封装,将持久层的功能与核心业务代码进行解耦,保证了持久层的耦合度,专业的模块,做专业的事,便于后期管理。
- MyBatis 通过 XML 配置或注解,实现了将 SQL 语句和程序逻辑解耦,提供了优雅的方式来进行 SQL 语句的管理和维护。通过 MyBatis,可以将 SQL 语句与 Java 代码分离,通过配置文件对 SQL 进行管理,使得 SQL 语句的修改、维护和优化变得更加方便和灵活,减少了硬编码问题的产生。同时,MyBatis 提供了参数化查询的支持,避免了直接拼接参数到 SQL 语句中的安全隐患。
- 从写SQL方面来看,解决了一下几个问题
- 将具体实现逻辑与代码逻辑进行了解耦:SQL语句与逻辑分离,便于管理SQL,将SQL的内部实现进行了封装
- 参数化配置,减少了SQL拼接的复杂性。使得高级的SQL语句编写更为简易
# 个人理解
【1】简单的来说,这是一个从数据库里面捞数据的框架
为什么需要这样一个框架呢?因为我们没有这个框架的时候,我们就需要按照以前的JDBC方式。一步一步的第一步是去拿到MySQL 给我们提供的驱动信息,通过这个驱动去创建和数据库的连接,拿到连接之后,我们才能够写 SQL 做CRUD。
我们需要自己去封装这样的一个JDBC完成这些操作。我们每写一个项目,就要重新封装一个这样的 jdbc 的东西,对于开发工作来说,非常的不简洁,不美观、不优雅
【2】进一步来说,它是解决了我们以前从数据库里面捞数据的一些弊端,来自于我们的硬编码问题以及 SQL 难以维护的问题
场景:首先我们的配置都是直接写在代码里面的,这样就会有硬编码问题。而且我们的SQL 语句都是写在代码里面的,这让我们难以管理数量庞大的数据库语句。更好的方式是将它解耦出来,把它放到另外一个文件中。
* 将具体实现逻辑与代码逻辑进行了解耦:SQL语句与逻辑分离,便于管理SQL,将SQL的内部实现进行了封装
* 参数化配置,减少了SQL拼接的复杂性。使得高级的SQL语句编写更为简易
【3】那么它的做法呢,就是提供给我们 一个一个的 XML 文件让我们编写,我们通过这些文件配置数据源,映射文件、SQL语句
那么我们只需要学习怎么向数据库里面按照他给定的格式去写我们的数据源映射文件以及 SQL 语句就好了,不需要一遍一遍的封装,解决各种复杂的依赖问题
并且保证了代码的优雅性,降低了代码量
这是一个伟大的框架,但让我用,我还是推荐 MyBatis plus
2
3
4
5
6
7
8
9
10
11
12
13
14
⭐⭐⭐ 我们为什么要用新版的 MyBatis 呢?
我们用过旧版的 MyBatis 都知道,在旧版的 MyBatis 中,环境配置以及 SQL 语句通常是使用 XML 进行编写的。在 XML 配置文件中,你可以定义数据源、映射Mapper 文件的位置,以及各种 SQL 语句(如增删改查)的映射关系。这种 XML 配置的方式在旧版本的 MyBatis 中是非常常见的。
- 需要熟悉最简单的就置
到现在比较流行的MyBatis-plus ,很大程度上简化了这些操作,使数据库的操作更加简洁、高效。
- 在写SQL方面:
- MyBatis-Plus 提供了通用的 CRUD 方法,通过继承 MyBatis-Plus 提供的接口,无需编写SQL语句即可进行大部分的单表增删改查操作。这样简化了开发过程,提高了开发效率。
- 强大的条件构造器,支持 Lambda 表达式,使得在查询时可以像编写 Java 代码一样进行条件组合,大大简化了复杂查询条件的构建。
- 附加功能:
- MyBatis-Plus 提供了强大的代码生成器功能,旧的generator都废弃掉了,大家都统一用MyBatis-Plus这一套
- 内置的分页插件Page简化了分页查询的操作,不再需要手动编写复杂的分页逻辑,只需简单配置即可实现分页查询。
- 乐观锁通常用于处理并发更新的情况,它通过在数据库表中增加一个版本号字段来实现。
@Version
- 逻辑删除是指在数据库中并不真正删除数据行,而是通过设置一个标识位(比如is_deleted)来表示数据是否被删除。在MyBatis-Plus中,你可以通过以下步骤实现逻辑删除:
@TableLogic
# 配置方式:XML or 注解
# 1、经典创建模式
以下是创建 SqlSession 的一般步骤:
1、配置 MyBatis 环境: 首先,你需要创建一个 MyBatis 的配置文件,其中包括数据库连接信息、映射文件路径、类型处理器等配置。
2、创建 SqlSessionFactory: 创建 SqlSessionFactory: 使用 MyBatis 的配置信息来构建 SqlSessionFactory 对象。SqlSessionFactory 是一个重量级的对象,通常在应用程序运行期间只需创建一次,它负责创建 SqlSession 实例。SqlSessionFactory 是共享的!!!!!!
String resource = "mybatis-config.xml"; // MyBatis 配置文件的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2
3
3、打开 SqlSession: 打开 SqlSession: 从 SqlSessionFactory 中获取 SqlSession 对象,可以通过这个对象来执行 SQL 语句。
try (SqlSession session = sqlSessionFactory.openSession()) {
// 执行数据库操作
MyMapper mapper = session.getMapper(MyMapper.class);
YourObject result = mapper.selectSomeData();
}
2
3
4
5
# 2、从XML资源创建Factory
从 XML 中构建 SqlSessionFactory
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file://
URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。
更老的创建方式
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。后面会再探讨 XML 配置文件的详细内容,这里先给出一个简单的示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
当然,还有很多可以在 XML 文件中配置的选项,上面的示例仅罗列了最关键的部分。 注意 XML 头部的声明,它用来验证 XML 文档的正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
# 给他用起来
# Idea插件
- 使用 Mybatis 的时候,要安装一个 idea 插件:MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
# 配置
# POM依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16-SNAPSHOT</version>
</dependency>
2
3
4
5
# 日志
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
# PageHelper
插件自行了解
# 原理
# Mybatis的执行过程
1、SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,
SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,
而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是
局部方法变量)。
2、SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为
MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个
MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用
MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。
由于 SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多
个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导
致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。
3、因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以
说 SqlSessionFactory 的最佳作用域是应用作用域。
4、如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接
(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback
等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这
条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所
以用 try...catch...finally... 语句来保证其正确关闭。所以 SqlSession 的最佳的作用域是请求或方法作用域。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 使用说明
MyBatis 提供了两种使用方法:XML配置、注解。官方推荐简单的可以用注解,比较难的SQL语句推荐XML配置
- 使用上就是关于 XML 文件配置的一些注意事项,不懂的直接到官网搜,很简单(都是关于一些 name space、 maper 、
resultType
属性、resultMap绑定关系
之类的)
# 动态SQL
官网描述: MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你 就能体会到根据不同条件拼接 SQL 语句的痛苦。
例如拼接时要确保不能忘记添加必要的空格,还要注意 去掉列表最后一个列名的逗号。
利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语 句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。
在 MyBatis 之前的版本中,有 很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。 MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
-------------------------------
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
-------------------------------
2
3
4
5
6
7
8
9
10
11
12
13
14
# 缓存
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
真的是比较牛逼,之前一直没发现
要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
<cache/>
1基本上就是这样。这个简单语句的效果如下:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。 ————————————————https://mybatis.org/mybatis-3/zh_CN/sqlmap-xml.html#cache
一级缓存(默认存在的)
- 每个 sqlSession 中的缓存相互独立
- update 之后,缓存失效
session.clearCache();
//手动清除缓存
二级缓存
- 开启了二级缓存,都会在对应的 mapper 中 对查询结果进行缓存。这里可以配置最大的缓存大小
- 二级缓存在整个应用程序中被共享,当在不同的 SqlSession 中执行相同的查询时,会首先查找二级缓存,如果缓存中有对应的结果,则会直接返回结果,不需要再访问数据库。一级缓存是与 SqlSession 绑定的,它是在同一个 SqlSession 中执行相同查询时的缓存机制。
- 只有在会话提交或者关闭之后,一级缓存中的数据才会转到二级缓存中
# 缓存增强框架
MyBatis Ehcache Adapter - Reference Documentation (opens new window)
# 其他注意
# 注意
- 接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!
- 为了规范操作,在SQL的配置文件中,我们尽量将
Parameter
参数和resultType
都写上!
# 占位符的使用
绝大多数项目还是需要写一些XML 文件的,这是避免不了的
mybatis
提供了两种参数占位符:
#{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是
PreparedStatement
${} :拼接SQL。底层使用的是
Statement
,会存在SQL注入问题。!!!!真正开发中禁用!!!!!
注意:从上面两个例子可以看出,以后开发我们使用 #{} 参数占位符。
<select id=”selectlike”> select * from foo where bar like #{value} </select>
两个巧记的办法:
- 将 #{} 想象成一个像#号和大括号组成的小房子,表示一个安全的“容器”,用于安全地存放参数值,就像是把参数值放在一个安全的容器里一样。
- 将 #{} 比喻成一个保险箱。在 SQL 查询中,我们希望参数值像贵重物品一样被安全地存放,就像将参数值放进一个保险箱中一样,而问号则是保险箱的具体位置。
# XML转译字符
映射配置文件是xml类型的问题,而 > < 等这些字符在xml中有特殊含义,需要将这些符号进行转义
# 注解完成简单功能,配置文件完成复杂功能。
官网说明
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
选择何种方式来配置映射,以及是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松地在基于注解和 XML 的语句映射方式间自由移植和切换。
——https://mybatis.org/mybatis-3/zh_CN/getting-started.html (opens new window)
# 多参数接口指定 param
接口参数是多个时,在每个参数上都使用 @Param
注解。这样代码的可读性更高。