MyBatis
Posted 一只可爱的小狐狸
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis相关的知识,希望对你有一定的参考价值。
MyBatis
MyBatis发展
1)MyBatis 是 Apache 的一个开源项目 iBatis, 2010 年 6 月这个项目由 Apache Software Foundation 迁移到了 Google Code,随着开发团队转投 Google Code 旗下, iBatis3.x 正式更名为 MyBatis ,代码于 2013 年 11 月迁移到 Github
2)iBatis 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。 iBatis 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO)
MyBatis 简介
1) MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架
2) MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
3) MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录
为什么要使用 MyBatis – 现有持久化技术的对比
1) JDBC 1 SQL 夹在 Java 代码块里,耦合度高导致硬编码内伤 2 维护不易且实际开发需求中 sql 是有变化,频繁修改的情况多见
2) Hibernate 和 JPA 1 长难复杂 SQL,对于 Hibernate 而言处理也不容易 2 内部自动生产的 SQL,不容易做特殊优化 3 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。导致数据 库性能下降
3) MyBatis 1 对开发人员而言,核心 sql 还是需要自己优化 2 sql 和 java 编码分开,功能边界清晰,一个专注业务、一个专注数据
什么是MyBatis?
- MyBatis 是一款优秀的持久层框架,
- 它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(jdbc),io文件持久化
- 生活:冷藏,罐头,
为什么需要持久化?
- 有一些东西,不能让他丢掉
- 内存太贵了
持久层
Dao层、Service层、Controller层
- 完成持久化工作的代码块
- 层界限十分明显
为什么学mybatis?
- 帮助程序员将数据存入到数据库中
- 便于方便
- 传统的JDBC代码太过于复杂了,简化,框架,自动化
- 不用学习Mybatis也可以,学习了之后更容易上手
- 优点:
- 简单易学
- 灵活
- 解除sql与程序代码的耦合
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
最重要的一点:使用的人多!
MyBatis 全局配置文件
MyBatis 全局配置文件
- The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves.
MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings )和属性 (properties)信息。
- 文件结构如下:
configuration 配置
properties 属性
settings 设置
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
databaseIdProvider 数据库厂商标识
mappers 映射器
properties 属性
-
可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可 通过 properties 元素的子元素来配置
-
然而 properties 的作用并不单单是这样,你可以创建一个资源文件,名为 jdbc.properties 的文件,将四个连接字符串的数据在资源文件中通过键值 对 (key=value)的方式放置,不要任何符号,一条占一行
driverClassName=com.mysql.cj.jdbc.Driver
userName=root
password=123456
url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&serverTimezone=UTC
3)在 environment 元素的 dataSource 元素中为其动态设置
<environments default="oracle">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="$jdbc.driver" />
<property name="url" value="$jdbc.url" />
<property name="username" value="$jdbc.username" />
<property name="password" value="$jdbc.password" />
</dataSource>
</environment>
</environments>
settings 设置
-
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
typeAliases 别名处理
-
类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类
<typeAlias type="com.cutestFox.model.Student" alias="Student"/> </typeAliases>
-
类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简 单类名小写
environments 环境配置
-
MyBatis 可以配置多种环境,比如开发、测试和生产环境需要有不同的配置
-
每种环境使用一个 environment 标签进行配置并指定唯一标识符
-
可以通过environments标签中的default 属性指定一个环境的标识符来快速的切换环境
-
environment-指定具体环境 id:指定当前环境的唯一标识 transactionManager、和 dataSource 都必须有
dataSource
type: UNPOOLED | POOLED | JNDI | 自定义 UNPOOLED:不使用连接池, UnpooledDataSourceFactory POOLED:使用连接池, PooledDataSourceFactory
JNDI: 在 EJB 或应用服务器这类容器中查找指定的数据源
自定义:实现 DataSourceFactory 接口,定义数据源的获取方式。
databaseIdProvider 数据库厂商标识
-
MyBatis 可以根据不同的数据库厂商执行不同的语句
-
配置了 databaseIdProvider 后,在 SQL 映射文件中的增删改查标签中使用 databaseId 来指定数据库标识的别名
select * from tbl_employee where id = #id -
MyBatis 匹配规则如下:
1 如果没有配置 databaseIdProvider 标签,那么 databaseId=null
2 如果配置了 databaseIdProvider 标签,使用标签配置的 name 去匹配数据库信息, 匹配上设置 databaseId=配置指定的值,否则依旧为 null
3 如果 databaseId 不为 null,他只会找到配置 databaseId 的 sql 语句
4 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的 所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者 会被舍弃
mappers 映射器
-
用来在 mybatis 初始化的时候,告诉 mybatis 需要引入哪些 Mapper 映射文件
-
mapper 逐个注册 SQL 映射文件
resource : 引入类路径下的文件
url : 引入网络路径或者是磁盘路径下的文件
class : 引入 Mapper 接口. 有 SQL 映射文件 , 要求 Mapper 接口与 SQL 映射文件同名同位置. 没有 SQL 映射文件 , 使用注解在接口的方法上写 SQL 语句.
<mappers>
<mapper resource="EmployeeMapper.xml" />
<mapper class="com.atguigu.mybatis.dao.EmployeeMapper"/>
<package name="com.atguigu.mybatis.dao"/>
</mappers>
-
使用批量注册,这种方式要求 SQL 映射文件名必须和接口名相同并且在同一目录下
MyBatis 映射文件
Mybatis 映射文件简介
-
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射 器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比, 你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通 的方法做的更好。
-
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序): cache – 给定命名空间的缓存配置。 cache-ref – 其他命名空间缓存配置的引用。 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加 载对象。
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语
Mybatis 使用 insert|update|delete|select 完成 CRUD
select
-
Mapper 接口方法
public Employee getEmployeeById(Integer id );
-
Mapper 映射文件
select * from tbl_employee where id = $_parameter
insert
-
Mapper 接口方法
public Integer insertEmployee(Employee employee);
-
Mapper 映射文件
insert into tbl_employee(last_name,email,gender) values(#lastName,#email,#gender)
update
-
Mapper 接口方法
public Boolean updateEmployee(Employee employee);
-
Mapper 映射文件
update tbl_employee set last_name = #lastName, email = #email, gender = #gender where id = #id
delete
-
Mapper 接口方法
public void deleteEmployeeById(Integer id );
-
Mapper 映射文件
delete from tbl_employee where id = #id
参数传递
参数传递的方式
-
单个参数 可以接受基本类型,对象类型。这种情况 MyBatis 可直接使用这个参数,不需要经过任 何处理。
-
多个参数 任意多个参数,都会被 MyBatis 重新包装成一个 Map 传入。Map 的 key 是 param1, param2,或者 0,1…,值就是参数的值
-
命名参数 为参数使用@Param 起一个名字,MyBatis 就会将这些参数封装进 map 中,key 就是我 们自己指定的名字
-
POJO 当这些参数属于我们业务 POJO 时,我们直接传递 POJO
-
Map 我们也可以封装多个参数为 map,直接传递
-
Collection/Array 会被 MyBatis 封装成一个 map 传入, Collection 对应的 key 是 collection,Array 对应的 key 是 array. 如果确定是 List 集合,key 还可以是 list.
参数处理
-
参数位置支持的属性: javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName、 expression
-
实际上通常被设置的是:可能为空的列名指定 jdbcType ,例如:
insert into orcl_employee(id,last_name,email,gender)
values(employee_seq.nextval,#lastName, ,jdbcType=NULL ,#email,#ge
nder)
参数的获取方式
-
#key:获取参数的值,预编译到 SQL 中。安全。
-
key:获取参数的值,拼接到 SQL 中。有 SQL 注入问题。ORDER BY name
select 查询的几种情况
-
查询单行数据返回单个对象
public Employee getEmployeeById(Integer id );
-
查询多行数据返回对象的集合
public List getAllEmps();
-
查询单行数据返回 Map 集合
public Map getEmployeeByIdReturnMap(Integer id );
-
查询多行数据返回 Map 集合 @MapKey(“id”) // 指定使用对象的哪个属性来充当 map 的 key
public Map getAllEmpsReturnMap();
resultType 自动映射
-
autoMappingBehavior 默认是 PARTIAL,开启自动映射的功能。唯一的要求是列名和 javaBean 属性名一致
-
如果 autoMappingBehavior 设置为 null 则会取消自动映射
-
数据库字段命名规范,POJO 属性符合驼峰命名法,如 A_COLUMN aColumn,我们可 以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true
resultMap 自定义映射
-
自定义 resultMap,实现高级结果集映射
-
id :用于完成主键值的映射
-
result :用于完成普通列的映射
-
association :一个复杂的类型关联;许多结果将包成这种类型
-
collection : 复杂类型的集合
MyBatis 动态 SQL
MyBatis 动态 SQL
-
动态 SQL 是 MyBatis 强大特性之一。极大的简化我们拼装 SQL 的操作
-
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似
-
MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作 if choose (when, otherwise) trim (where, set) foreach
-
OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的 表达式语言,通过它可以非常方便的来操作对象属性。 类似于我们的 EL,SpEL 等
访问对象属性: person.name
调用方法: person.getName()
调用静态属性/方法: @java.lang.Math@PI @java.util.UUID@randomUUID()
调用构造方法: new com.atguigu.bean.Person(‘admin’).name
运算符: +,-*,/,%
逻辑运算符: in,not in,>,>=,<,<=,==,!=
if where
-
If 用于完成简单的判断.
-
Where 用于解决 SQL 语句中 where 关键字以及条件中第一个 and 或者 or 的问题
select id , last_name ,email , gender from tbl_employee and id = #id and last_name = #lastName and email = #email and gender = #gender
trim
- Trim 可以在条件判断完的 SQL 语句前后 添加或者去掉指定的字符
prefix: 添加前缀
prefixOverrides: 去掉前缀
suffix: 添加后缀
suffixOverrides: 去掉后缀
<select id="getEmpsByConditionTrim" resultType="com.cutestfox.mybatis.beans.Employee">
select id , last_name ,email , gender
from tbl_employee
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id = #id and
</if>
<if test="lastName!=null && lastName!=""">
last_name = #lastName and
</if>
<if test="email!=null and email.trim()!=''">
email = #email and
</if>
<if test=""m".equals(gender) or
"f".equals(gender)">
gender = #gender
</if>
</trim>
</select>
set
-
set 主要是用于解决修改操作中 SQL 语句中可能多出逗号的问题
update tbl_employee last_name = #lastName, email = #email , gender = #gender where id =#id
choose(when、otherwise)
-
choose 主要是用于分支判断,类似于 java 中的 switch case,只会满足所有分支中的一个
select id ,last_name, email,gender from tbl_employee id = #id last_name = #lastName email = #email gender = 'm'
foreach
- foreach 主要用户循环迭代
collection: 要迭代的集合
item: 当前从集合中迭代出的元素
open: 开始字符
close:结束字符
separator: 元素与元素之间的分隔符
index: 迭代的是
List 集合:
index 表示的当前元素的下标 迭代的 Map 集合:
index 表示的当前元素的 key
<select id="getEmpsByConditionForeach" resultType="com.cutestfox.mybatis.beans.Employee">
select id , last_name, email ,gender from tbl_employee where id in
<foreach collection="ids" item="curr_id" open="(" close=")"
separator="," >
#curr_id
</foreach>
</select>
sql
-
sql 标签是用于抽取可重用的 sql 片段,将相同的,使用频繁的 SQL 片段抽取出来,单 独定义,方便多次引用. 2) 抽取 SQL:
select id , last_name, email ,gender from tbl_employee -
引用 SQL:
MyBatis 缓存机制
缓存机制
-
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以 极大的提升查询效率
-
MyBatis 系统中默认定义了两级缓存 一级缓存 二级缓存
-
默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启。
-
二级缓存需要手动开启和配置,他是基于 namespace 级别的缓存。
-
为了提高扩展性。MyBatis 定义了缓存接口 Cache。我们可以通过实现 Cache 接口来自 定义二级缓存
一级缓存的使用
-
一级缓存(local cache), 即本地缓存, 作用域默认为 sqlSession。当 Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空。
-
本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作 用域.
-
在 mybatis3.1 之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置
-
一级缓存的工作机制 同一次会话期间只要查询过的数据都会保存在当前 SqlSession 的一个 Map 中 key: hashCode+查询的 SqlId+编写的 sql 查询语句+参数
一级缓存失效的几种情况
-
不同的 SqlSession 对应不同的一级缓存
-
同一个 SqlSession 但是查询条件不同
-
同一个 SqlSession 两次查询期间执行了任何一次增删改操作
-
同一个 SqlSession 两次查询期间手动清空了缓存
二级缓存的使用
-
二级缓存(second level cache),全局作用域缓存
-
二级缓存默认不开启,需要手动配置
-
MyBatis 提供二级缓存的接口以及实现,缓存实现要求 POJO 实现 Serializable 接口
-
二级缓存在 SqlSession 关闭或提交之后才会生效
-
二级缓存使用的步骤:
1 全局配置文件中开启二级缓存
2 需要使用二级缓存的映射文件处使用 cache 配置缓存
3 注意:POJO 需要实现 Serializable 接口
-
二级缓存相关的属性
1 eviction=“FIFO”:缓存回收策略: LRU – 最近最少使用的:移除最长时间不被使用的对象。 FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 默认的是 LRU。
2 flushInterval:刷新间隔,单位毫秒 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
3 size:引用数目,正整数 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
4 readOnly:只读,true/false true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被 修改。这提供了很重要的性能优势。 false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全, 因此默认是 false
缓存的相关属性设置
-
全局 setting 的 cacheEnable: 配置二级缓存的开关,一级缓存一直是打开的。
-
select 标签的 useCache 属性: 配置这个 select 是否使用二级缓存。一级缓存一直是使用的
-
sql 标签的 flushCache 属性: 增删改默认 flushCache=true。sql 执行以后,会同时清空一级和二级缓存。 查询默认 flushCache=false。
-
sqlSession.clearCache():只是用来清除一级缓存
MyBatis 逆向工程
逆向工程
- MyBatis Generator: 简称 MBG,是一个专门为 MyBatis 框架使用者定制的代码生成器, 可以快速的根据表生成对应的映射文件,接口,以及 bean 类。支持基本的增删改查, 以及 QBC 风格的条件查询。但是表连接、存储过程等这些复杂 sql 的定义需要我们手 工编写
逆向工程的配置
-
导入逆向工程的 jar 包 mybatis-generator-core-1.3.2.jar
-
编写 MBG 的配置文件
<?xml version="1.0" encoding="UTF-8"?> -
运行代码生成器生成代码
@Test
public void testMBG() throws Exception
List warnings = new ArrayList();
boolean overwrite = true;
File configFile = new File(“mbg.xml”);
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
以上是关于MyBatis的主要内容,如果未能解决你的问题,请参考以下文章