文章目录
1. MyBatis简介
1.1 什么是MyBatis
- MyBatis是一个半自动化(SQL自己编写, 其余交给框架执行)的持久层(DAO)框架。
- 特点: SQL在配置文件中编写, 和Java代码分开, 功能边界清晰, 一个专注业务, 一个专注数据。
1.2 JDBC和Hibernate、JPA的比较
JDBC
- SQL和Java代码耦合
- 维护不易且实际开发中SQL是有变化、频繁修改的情况多。
Hibernate、JPA
- SQL长难复杂
- 内部自动生产的SQL, 不易做优化处理
- 基于全映射的全自动框架(编写SQL - 预编译 -设置参数 - 执行 - 封装结果全部交给框架执行), 大量字段的POJO进行部分映射时比较困难, 导致数据库性能低下
1.3 MyBatis下载、第一个程序
下载地址: https://github.com/mybatis/mybatis-3/tree/mybatis-3.5.3
往下拉
点击这个
下载压缩包并解压获取jar包导入到项目中
或者在Maven中导入依赖
程序流程演示
第一种
-
写mybatis-config.xml(mybatis全局配置)文件, 把数据库部分的参数填上
文件内容如下
代码出自mybatis的官方文档: https://mybatis.org/mybatis-3/zh/getting-started.html# -
写XXXMapper.xml文件(对于数据库的表 例如User表就是UserMapper.xml文件)
注意修改全局配置文件Mybatis-config.xml
-
写程序
注意
第二种(推荐使用)
- 写mybatis - config.xml文件, mybatis-config.xml的mappers映射为xxxMapper.xml文件
- 写接口, 接口中定义增删改查方法
- 在UserMapper.xml中设定名称空间为接口, 各个标签id值为接口中定义的方法名
- 写程序
(1) 读取全局配置文件mybatis-config.xml获取流
(2) 获取SqlSessionFactory实例
(3) 获取SqlSession实例
(4) 使用getMapper(接口)方法获取由mybatis创建的接口实现类代理对象,
填充占位符
(5) 最后注意关闭sqlSession(注意sqlsession是非线程安全的, 不能在类里以私有化对象的形式写), 调用close方法
2. Mybatis-config
2.1 properties
使用properties标签可以外部引入properties配置文件
2.2 settings
settngs标签可以设置mybatis的运行时行为, 具体的settings设置参考mybatis官方文档。
lazyLoadingEnabled(默认false)
延迟加载: 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。
aggressiveLazyLoading(默认false)
开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载
cacheEnabled(默认true)
开启二级缓存
2.3 typeAliases
别名处理器, 对于指定的Java类型起别名, 不写别名默认别名是类名小写。
-
单独起别名
-
批量起别名
-
使用@Alias注解进行区分
2.4 typeHandlers
2.5 plugins
2.6 environments
- environments 环境配置, mybatis可以配置多种环境 default指定使用的某种环境。
- environment 配置一个具体的环境信息, 必须有两个标签, id(唯一标识)
- transactionManager 事务管理器 属性:type
- JDBC
- Manager
- 自定义事务管理器, 实现TransactionFactory接口, 属性值是全类名
- dataSource 数据源 属性: type
- UNPOOLED(不使用连接池)
- POOLED(使用连接池)
- JNDI
- transactionManager 事务管理器 属性:type
2.7 databaseidProvider
2.8 mappers
将我们写好的sql映射文件注册到全局配置文件中
mappers的属性
- resource: 引用类路径下
- url: 引用网络路径
- class: 注册接口
1. 有SQL映射文件, 当接口和SQL映射文件在同一目录下并且文件名相同。
2. 没有SQL映射文件, SQL使用@Resource注解写在接口上。
3. Mybatis-SQL映射
3.1 insert、update、delete
-
定义接口, 定义方法
-
写映射文件, 并注册到全局配置文件当中
note:
(1) Mybatis允许增删改直接定义以下几种类型的返回值: Boolean、Long、Integer、
(2) OpenSession方法的无参数效果是不会自动提交, 我们执行完后需要手动提交, 最后要关闭资源
(3) 获取自增主键的值
在SQL映射文件中设置
useGeneratedKeys 是否获取自增主键的值 true | false
keyProperty 自增主键的字段名, mybatis获取到主键值后封装到对象中对应的属性。(4) 参数处理
单个参数 #{参数} mybatis不会做特殊处理
多个参数 mybatis会做特殊处理, 多个参数会被封装成一个map, #{}就是从map中获取指定key的值, 可以在设定方法形参时使用@Param给参数起别名, 这样我们就能通过#{别名}来获取参数。
POJO:如果多个参数正好是我们业务逻辑的数据模型(实体), 我们可以直接#{属性名}获取
如果多个参数不是我们业务逻辑的数据, 没有对应的实体, 我们可以使用Map集合,直接通过#{key}获取值
(5) #和$的区别- #是以预编译的形式, 将参数设置到sql语句当中, PreparedStatement, 防止SQL注入
- $取出的值直接拼接在SQL语句中, 会有SQL安全问题。
3.2 select
3.2.1 select常见属性
id 唯一标识, 绑定接口中定义的方法名
parameterType 参数类型, 这个是可选的, 因为Mybatis可以通过TypeHandler来推断出具体传入语句的参数
resultType 返回值类型, 如果是集合,则应该是集合中存储的元素类型, 和resultMap不能同时使用
resultMap 自定义某个JavaBean的封装规则
databaseId 数据库标识别名
3.2.2 获取List
3.2.3 获取Map
返回单条记录的map
返回多条记录的map
3.2.3 ResultMap自定义封装规则
3.2.4 ResultMap实现联合查询
使用association和collection标签
第一种: 注入对象属性
第二种: 分步查询(子查询)
第三种: 类中的集合属性
3.2.5 discriminator鉴别器
- mybatis可以使用discriminator鉴别器判断某列的值, 然后根据某列的值改变封装行为
3.3 动态SQL
- 动态 SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作。
- MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作。
3.3.1 if判断
- 有点类似JSTL中的<c:if/>
- 这个语句只是演示if的使用方法,该SQL存在一定的弊端, 当 id = null 时, sql为where and eName …
明显具有语法错误 - 因为是在xml中, 部分符号需要转义, 例如 “” 的转义就是 " ;" ; 可以在w3chool的xml文档中查到实体符号
改进方式一: where 1=1
改进方式二:使用Where标签(and或or要写前面, 这样多余的mybaits会自动去除, 而后面的不会)
改进方式三: 自定义字符串截取, 使用trim标签
trim标签- prefix 前缀
- prefixOverrides 前缀覆盖:去掉整个字符串前面多余的字符
- suffix 后缀
- suffixOverrides 后缀覆盖:去掉整个字符串后面多余的字符
3.3.2 choose分支
- 类似Java中的switch case结构
- choose(when、otherwise)
3.3.3 update利用set if和trim实现动态更新
set + if 组合实现动态更新
使用trim方式, 前缀为set, 后缀覆盖,
3.3.4 Foreach
遍历元素
Mysql批量插入字段
第二种方式: 需要修改properties文件
3.3.5 内置参数_parameter和_databaseId
- _parameter : 代表整个参数, 单个参数, _parameter就是这个参数, 多个参数, _parameter就是参数map集合
- _databaseId : 如果配置了databaseIdProvider标签, databaseId就是代表当前数据库的别名
3.3.6 bind绑定
- 作用: 将OGNL表达式的值绑定到一个变量上, 方便使用
- 注意: bind绑定需要在判断变量不是空的情况下进行绑定, 否则就会出现空指针异常。
3.3.6 sql抽取可重用片段
- 把经常需要查询的列名. 或者插入用的列名保存到sql标签中
- 通过include调用
- include内部可以定义一些参数, 然后在重用片段中通过${参数名}获取
4. Mybatis - 缓存机制
4.1 缓存机制的概念
- mybatis包含一个非常强大的查询缓存的特性, 它可以非常方便的配置和定制, 缓存可以极大的提升查询效率
- mybatis系统中默认定义了两级缓存
- 一级缓存和二级缓存
- 默认情况下, 只有一级缓存(SqlSession级别的缓存, 也叫本地缓存开启)。
- 二级缓存(全局)需要手动开启和配置, 他是基于namespace级别的缓存。
- 为了提高扩展性, Mybatis定义了缓存接口Cache, 我们可以通过实现Cache接口来自定义二级缓存。
4.1 一级缓存
4.1.1 基本介绍
- SqlSession级别, 与数据库同一次会话期间查询到的数据会放到本地缓存, 如果之后需要复用, 直接从缓存中获取
- 演示
4.1.2 一级缓存失效的4种情况
- 开启了新的SqlSession
- SqlSession相同, 查询条件不同(当前缓存中还没有该数据)
- SqlSeesion相同, 两次相同的查询之间进行了增删改操作(可能对当前数据有影响)
- 手动清除了SqlSession缓存, sqlSeesion.clearCache()
4.2 二级缓存
4.2.1 基本介绍
- 基于namespace的缓存, 一个namespace就对应一个二级缓存
- 工作机制
- 一个会话, 查询一条数据, 这个数据就会放在当前会话的一级缓存中。
- 如果会话关闭, 一级缓存中的数据会被保存到二级缓存中, 新的会话查询信息, 就可以参照二级缓存。
- 不同的namespace查出的数据放到自己的缓存中, 是一个map集合。
4.2.2 二级缓存的使用
使用步骤
-
开启全局二级缓存配置, 在全局配置文件中通过设置settings运行时行为来设定
-
在sql映射文件中使用cache标签进行配置, 二级缓存有一些默认的策略需要配置
-
pojo需要实现序列化, 所以要实现Serializable接口
4.3 和缓存相关的设置和属性
-
全局配置文件中的settings设置
cacheEnabled = “false” 关闭二级缓存(一级缓存一直可用) -
每个select标签都有useCache=""
- true 使用二级缓存
- false 不使用二级缓存
-
每个增删改查标签都有flushCache=""
- true 增删改查完成后就会清除缓存(一级和二级)
- false 增删改查完成后不清除缓存
-
sqlSession.clearCache()方法只会手动清除一级缓存
-
localCacheSession:本地缓存作用域, 当设置为STATEMENT时会保存在会话缓存中, 会禁用一级缓存
4.4 缓存原理图示
5. Mybatis - 整合Spring
- https://github.com/mybatis/spring/releases 这个网址下载mybatis-spring, 注意版本适配。
- 要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-2.0.6.jar 文件和相关依赖即可。
如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:
- 引入Spring、JSTL、日志、相关包
6. Mybatis - 逆向工程
6.1 MBG基本介绍
-
MyBatis Generator: 简称 MBG, 是一个专门为Mybatis框架使用者定制的代码生成器, 可以快速的根据表生成对应的映射文件, 接口, 以及bean类, 支持基本的CURD, 以及QBC风格的条件查询, 但是表连接、存储过程这些复杂SQL的定义需要手动编写
-
官方文档地址 : http://www.mybaits.org/generator/
-
官方工程地址 : http://github.com/mybatis/generator/releases 找到这个点击下载
-
在Maven中引入依赖的方式
6.2 生成代码流程
- 编写mbg.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3">
<jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver"
connectionURL="jdbc:db2:TEST"
userId="db2admin"
password="db2admin">
</jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="test.model" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="test.xml" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
<property name="useActualColumnNames" value="true"/>
<generatedKey column="ID" sqlStatement="DB2" identity="true" />
<columnOverride column="DATE_FIELD" property="startDate" />
<ignoreColumn column="FRED" />
<columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
</table>
</context>
</generatorConfiguration>
- 执行生成代码, xml处修改即可
public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
List<String> generatorWarnings = new ArrayList<String>();
File file = new File("src/main/resources/generator.xml");
ConfigurationParser cp = new ConfigurationParser(generatorWarnings);
Configuration config = cp.parseConfiguration(file);
DefaultShellCallback shellCallback = new DefaultShellCallback(true);
MyBatisGenerator generator = new MyBatisGenerator(config,shellCallback,generatorWarnings);
generator.generate(null);
}
- 运行无报错, 结果如下
6.3 mbg.xml配置文件详解
- jdbcConnection: 指定如何连接到目标数据库
- javaTypeResolver: Java类型解析器
- javaModelGenerator: 指定javaBean的生成策略
- targetPackage=“test.model” 目标包名
- targetProject="\MBGTestProject\src" 目标工厂
- sqlMapGenerator: sql映射(Mapper.xml)生成策略
- targetPackage=“test.model” 目标包名
- javaClientGenerator: 指定mapper接口所在位置
- table: 指定要逆向分析那些表, 根据表创建javabean