MyBatis学习
(一)MyBatis概述
传统JDBC劣势
1、代码繁琐
2、表关系维护复杂
3、硬编码
4、性能问题
ORM框架概念 -- Object-Relation Mapping 对象关系映射
ORM是一种规范,将简单Java对象(POJO)和数据库进行映射,使数据库表中的记录和POJO对象一一对应。
在Java应用领域流行的ORM框架有Hibernate、MyBatis等,
1、Hibernate
封装性好,开发人员通过XML映射文件(或注解)定义好映射规则后,H 根据规则自动生成SQL语句并调用JDBC的API执行。
无法根据不同条件组装不同SQL
对多表关联和复杂SQL查询支持较差
不能有效支持SQL优化
。。。等
2、MyBatis
手动提供POJO、SQL语句并匹配映射关系。
半自动化的ORM框架
核心思想:剥离出程序中大量SQL语句并将这些SQL语句配置到映射文件中。
支持动态列、动态表名、存储过程,简易日志,缓存和级联功能
MyBatis功能架构
API接口层 数据查询、新增、更新、删除等接口,获取配置接口
数据处理层 参数映射 -> SQL解析 -> SQL执行 -> 结果映射
基础支持层 连接管理、事务管理、配置加载、缓存处理、配置框架
MyBatis工作流程
配置文件
-->SqlSessionFactory -> SqlSession(核心对象) -> Executor(执行器) -> MappedStatement
映射文件
MyBatis重要API(具体API、网上查阅)
SqlSession: 首要作用是持久化操作。生命周期为数据库处理事务的过程,要及时关闭。
SqlSession线程不安全,应注意多线程状态下的SqlSession对象,操作时注意隔离级别、数据库锁
SqlSessionFactory:创建SqlSession对象,SqlSessionFactory对象由SqlSessionFactoryBuilder对象创建 .build()方法
.build()方法的两种形式
SqlSessionFactory build(InputStream inputStream [, String environment] [, Properties props])
SqlSessionFactory build(Configuration config)
SqlSession: 由SQLSessionFactory对象的openSession()方法创建
.openSession()有多种形式 具体查表 常用的有
SqlSession openSession()
T selectOne(String statement)
Map selectMap(String statement, String mapKey)
T getMapper(Class type) 获取映射器
... == 还有很多
Executor:Executor(执行器)接口有两个实现类,其中BaseExecutor有三个继承类分别是
BatchExecutor(重用语句并执行批量更新),
ReuseExecutor(重用预处理语句prepared statement,跟Simple的唯一区别就是内部缓存statement),
SimpleExecutor(默认,每次都会创建新的statement)。以上三个就是主要的Executor。
Mybatis在Executor的设计上面使用了装饰器模式,
我们可以用CachingExecutor来装饰前面的三个执行器目的就是用来实现缓存。
MappedStatement:MappedStatement就是用来存放我们SQL映射文件中的信息包括sql语句,输入参数,输出参数等等。
一个SQL节点对应一个MappedStatement对象。
代码操作见IDEA
(二)MyBatis配置文件结构
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://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>
<databseIdProvider type=""/> --数据厂商标识
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
<properties>元素 用于配置属性 通过<property> 或 peoperties文件配置MyBatis
子元素:如 mybatis-config-property.xml
properties:在src目录下新建一个db.properties文件 如mybatis-config-properties.xml
配置文件中的值优于子元素的值
<settings>元素 控制MyBatis运行时的状态和行为。
cacheEnabled -- 全局开启或关闭配置文件中所有映射器已配置的任何缓存
lazyLoadingEnabled -- 延迟加载的全局开关
aggressiveLazyLoading --
multipleResultSetsEnabled -- 是否允许单一语句返回多个结果集
useColumnLabel -- 使用列标签代表列名
logPrefix 参数值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>元素 给较长类的类名取一个别名
<typeAliases> <typeAlias alias="student" type = "com.ye.pojo.Student"/> </typeAliases>
<package name="com.ye.pojo"> 此时别名为此包内类名的小写
如果以扫描包的形式设置别名时,不愿用MyBatis默认的别名,可以再POJO类中添加注解@Alias
@Alias(value="stu")
同时一些常用JAVA类型也有MyBatis提供的别名
<typeHandlers>元素 类型处理器, JAVA->JDBC JDBC->JAVA 当为SQL语句设置参数或从结果中取值时
基本类型可满足基本需求。若不满足需求则可以先编写typeHandler类实现接口或继承,其次完成配置。加入到MyBatis配置文件汇中
该元素,知道就行。
<ObjectFactory>元素 对象工厂创建结果集对象 默认情况为DefaultObjectFactory类完成,实际开发中,需要自定义ObjectFactory
自定义OF的两个环节:编写OF类,其次完成配置。 MyBatis通过元素配置
<environments>元素 配置数据库信息
MyBatis支持多种环境,可以实现多个数据库使用相同的SQL映射
UNPOOLED POOLED JNDI 三种数据源
UNPOOLED 非连接池类型,只在每次被请求时才会打开和关闭连接
POOLED 连接池类型,维持有一定活跃量的连接对象。可配置多重属性
JNDI 能在EJB或应用服务器之列的容器中使用,容器可以集中在或在外部配置数据源,然后放置一个JNDI上下文的引用
initial_context 在InitialContext中寻找上下文,
data_source 引用数据源实例位置的上下文路径
<environment>元素定义运行环境 <transactionManager type="JDBC"> 配置事务管理器
JDBC和MANAGED
JDBC:提交、回滚、关闭等事务管理
MANAGED:交给容器管理事务
<mappers>元素 引入映射文件。包含POJO对象和数据表之间的映射信息,元素引导MyBatis找到映射文件并解析其中映射信息
1)相对于类路径的资源引用 resource
2)使用完全限定资源定位符(本地文件路径) < mapper url = "">
3)使用映射器接口实现类的完全限定类名 class
4)将包内的映射器接口实现全部注册为映射器 <package>
MyBatis映射文件结构
select元素 查询语句 parameterType resultType 类名/别名
insert元素
delete元素
update元素
sql元素 定义可重用的SQL代码片段。
<sql id = "studentCols"> </sql>
<include />引入sql代码 即统一列名,方便更改
ResultMap元素 映射结果集 包含多个子元素 封装并实现了一些JDBC没有提供的功能
(三)MyBatis的关联映射
3.1表与表之间的关系 一对一 一对多 多对多
3.2一对一
使用MyBatis处理一对一的表关系,在映射文件中加入<association>元素 -> 映射文件<resultMap>元素的子元素
详见代码ch02
3.3一对多
3.4多对多
3.5主键映射
获取主键值可以通过配置映射文件中<insert>元素完成映射
useGeneratedKeys 获取数据库内部产生的主键值
keyProperty 指定主键
如果数据库中主键非自增,则使用<insert>中的<selectKey>子元素获取主键值
(四)动态SQL MyBatis提供的拼接SQL语句的机制,在映射文件中,可以通过动态元素灵活组装SQL语句
--详情请见代码ch04
4.1.1 常用元素有 if choose trim foreach
4.1.2 if元素 用于条件判断,常与test属性联合使用 根据需求动态控制where子句内容
4.1.3 choose when otherwise 三元素 choose包含when和otherwise
choose 相当于Java中的Switch语句 至少要包含一个when元素 0/1个otherwise
4.1.4 where元素 通常与if联用 如果where后面有以and或者or开头的内容时则自动将and 和 or 删除
即方便于使用 where 1 = 1 处理and
4.1.5 set元素 适用于update语句中。处理set后面以逗号结尾的内容,将逗号删除。即动态设置set 并消除无关逗号
4.1.6 trim元素 删除多余关键字 可以直接实现where 和 set元素功能
四种属性:prefix前缀 prefixOverrides前缀后面是'xx'时删除后面的xx suffix后缀 suffixOverrides
4.1.7 foreach元素 用于遍历。支持数组、List或Set接口的集合
collection item index open/close separator 5个属性
通常用于SQL语句的in关键字
4.1.8 bind元素 将OGNL表达式的值绑定到一个变量,对变量的引用更简单。提高可移植性。
如在一些值的前后加上通配符
4.2 注解 实现POJO对象和数据表之间的映射 直接将SQL语句写在接口上。
要创建接口。再在Mapper中配置接口。
4.2.1 select注解
4.2.2 insert注解
4.2.3 update注解
4.2.4 delete注解
4.2.5 param注解
(五)MyBatis缓存处理
5.1 MyBatis缓存机制
缓存将程序使用频率较高的数据存储在内存中。MyBatis支持的缓存分为一级缓存和二级缓存
一级缓存是SQLSession级别的缓存,MyBatis在SqlSession对象中引入一个HashMap对象作为存储数据的区域
二级缓存是Mapper级别的缓存,多个SqlSession去操作同一个Mapper的Sql语句,二级是跨SqlSession的。
一级缓存默认开启,二级缓存手动开启
5.2.1 一级缓存原理
当操作与缓存中的操作不同时,会清空缓存,重新输入。缓存也可手动删除
5.2.2 一级缓存应用
5.3.1 二级缓存原理
作用域范围更大,可以跨多个SQlSession对象,可自定义缓存源。
清空缓存是为了防止程序误读内容。
5.3.2 二级缓存的配置
在全局配置中打开二级缓存
<settings> <setting name="cacheEnable" value="true"/></settings>
在映射文件中打开二级缓存
<cache></cache> - eviction flushInterval size readonly
5.3.3 二级缓存应用
打开二级缓存 第一次操作结束之后才写入二级缓存
全局配置文件 <setting name="cacheEnabled" value="true"/>
映射文件 <cache></cache>
pojo类 implements Serializable 可序列化
5.4.1 EhCache简介 分布式缓存将缓存数据进行集中管理
ehcache.xml进行配置文件