深入浅出Mybatis技术原理笔记(一)

mybatis

myBatis配置详情

Mybatis配置 XML 文件的层次结构

<?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> <!--属性--> <properties/> <!-- 设置 --> <settings> <!-- 驼峰命名 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!-- 类型命名 --> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> </typeAliases> <!-- 类型处理器 --> <typeHandlers/> <!-- 对象工厂 --> <objectFactory type=""/> <!-- 插件 --> <plugins> <plugin interceptor=""></plugin> </plugins> <!-- 配置环境 --> <environments default=""> <!--环境变量--> <environment id=""> <!--事务管理器--> <transactionManager type=""></transactionManager> <!--数据源--> <dataSource type=""></dataSource> </environment> </environments> <!--数据库厂商表示--> <databaseIdProvider type=""/> <!-- 映射器 --> <mappers></mappers> </configuration>

1. properties 元素

properties 是一个配置属性的元素,能让我们在配置文件的上下文中使用它,MyBatis 提供了3种配置方式。

  • property 子元素,配置数据库的连接方式
  • properties 配置文件
  • 程序参数传递

2. settings 设置

3. typeAliases 自定义别名

4. typeHandler 自定义数据类型处理器

<typeHandlers> <typeHandler jdbcType="VARCHAR" javaType="string" handler="com.isxyf.mysql.typeHandler.MyStringTypeHandler"/> </typeHandlers>

上面定义的数据库类型为 VARCHAR 型,当 Java 的参数为 string 型的时候,我们将使用 MyStringTypeHandler 进行处理。

5. ObjectFactory

当 MyBatis 在构建一个结果返回的时候,都会使用 ObjectFactory(对象工厂)去去构建 POJO,在 MyBatis 中可以定制自己的对象工厂,默认的 ObjectFactory 是由 `org.apache.ibatis.reflection.factory.DefaultObjectFactory 来提供服务。

<objectFactory type="com.isyxf.mysql.objectFactory.MyObjectFactory"> <property name="name" value="MyObjectFactory"/> </objectFactory>

这里配置了一个对象工厂 MyObjectFactory, 对它的要求是实现 ObjectFactory 的接口,实际上 DefaultObjectFactory 已经实现了 ObjectFactory 的接口,我们可以直接继承 DefaultObjectFactory 来简化变成。

public class MyObjectFactory extends DefaultObjectFactory { @Override public <T> T create(Class<T> type) { System.out.println("使用定制对象工厂的 create 方法构建单个对象"); return super.create(type); } @Override public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { System.out.println("使用定制对象工厂的 create 方法构建列表对象"); return super.create(type, constructorArgTypes, constructorArgs); } @Override public <T> boolean isCollection(Class<T> type) { return super.isCollection(type); } @Override public void setProperties(Properties properties) { System.out.println("定制属性:" + properties); super.setProperties(properties); } }

6. plugins 插件

使用插件将覆盖一些 MyBatis 内部核心对象的行为

7. environment 配置环境

8. mappers 映射器

引入映射器的方法很多,一般分为以下几种。

  1. 用文件路径引入映射器
<mapplers> <mapper resource=""/> </mapplers>
  1. 用报名引入映射器
<mappers> <package name="com.isyxf.redis.mapper"/> </mappers>
  1. 用类注册引入映射器
<mappers> <package name="com.isyxf.redis.mapper.BookesMapper"/> </mappers>

映射器的主要元素

元素名称 描述 备注
select 查询语句,最常用、最复杂的元素之一 可以自定义参数,返回结果集等
insert 插入语句 执行后返回一个整数,代表插入的条数
update 更新语句 执行后返回一个整数,代表更新的条数
delete 删除语句 执行后返回一个整数,代表删除的条数
sql 允许定义一部分的 SQL,然后在各个地方引用它 例如: 一张表列名,我们可以一次定义在多个SQL语句中使用
resultMap 用来描述从数据库结果集中来加载对象,它是最复杂、最强大的元素 它将提供映射规则
cache 给定命名空间的缓存配置 -
cache-ref 其他命名空间缓存配置的引用 -

其他相关功能

1)、插入后自动返回主键

<insert id="insertRole" parameterType="role" useGeneratedKeys="true" keyProperty="id"> <insert into t_role(role_name, note) value (${roleNmae}, ${note}) </insert>

这里我们传入的 role 对象 无需设置 id 的值,MyBatis 会用数据库的设置进行处理,这样做的好处是 MyBatis 插入的时候,它会回填 JavaBean 的 id值。

2)、#和$的区别
当我们设置的参数#{name}时,在大部分的情况下 MyBatis 会用创建预编译的语句,然后 MyBatis 为它设置值,而使用 ${name} MyBatis 就不会帮我们转 columns,而变为直出,不是作为 SQL 的参数进行设置了,只是这样对 SQL 而言是不安全的

3)、resultMap

4)、lazyLoadingEnabled 和 aggressiveLazy Loading
lazyLoadingEnabled: 开启延迟加载功能,aggressiveLazyLoading: ?

关于系统缓存

MyBatis 对缓存提供支持,在没有配置的默认情况下,它只开启一级缓存(一级缓存只是相对于同一个 SqlSession 而言)。所以在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 Mapper 的方法,往往只执行一次 SQL,因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中以后再查询的时候如果没有声明需要刷新,并且缓存没超时的情况下,SqlSession 都只会取出当前缓存的数据,而不会再次发送 SQL 到数据库。

SqlSessionFactory 的二级缓存默认是不开启的,开启二级缓存需要进行配置,实现二级缓存的时候 MyBatis 要求返回的 POJO 必须是可序列化的,也就是要求实现 Serializable 接口,配置的方法很简单只需要在映射的 XML 文件配置就可以开启缓存了。详细说明

<cache eviction="LRU" flushInterval="10000" size="1024" readOnly="true"/>

属性配置:

  • eviction: 代表的是缓存回收策略,目前 MyBatis 提供以下策略
    • LRU, 最近最少使用的,移除最长时间不用的对象
    • FIFO, 先进先出,按对象进入缓存的顺序来移除他们
    • SOFT, 软引用,移除基于垃圾回收器状态和软引用规则的对象
    • WEAK, 弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
  • flushInterval: 刷新间隔时间,单位为毫秒,这里配置的是 100 秒刷新,如果你不配置它,那么当 SQL 被执行的时候才会去刷新缓存
  • size: 引用数目,一个正整数代表缓存最多可以储存多少个对象,不宜设置过大,太大会导致 OOM
  • readOnly: 只读,数据只能读取不能被修改,这样的好处是我们可以快速的读取缓存,缺点是没法修改,默认值为 false
  • blocking: ?
  • type: ?

自定义缓存
系统缓存是 MyBatis 应用机器上的本地缓存,但是在大型服务机器上会使用各种不同的缓存服务器,比如现在十分流行的 redis 缓存,这个时候我们就需要实现 MyBatis 为我们提供的缓存接口 org.apache.ibatis.cache.Cache

public interface Cache { /** * 获取缓存编号 * @return */ public String getId() /** * 保存 key 值缓存对象 * @param key * @param value */ public void putObject(Object key, Object value) /** * 通过 key 获取缓存对象 * @param key * @return */ public Object getObject(Object key) /** * 通过 key 删除缓存对象 * @param key * @return */ public Object removeObject(Object key) /** * 清空缓存 */ public void clear() /** * 获取缓存对象大小 * @return */ public int getSize() /** * 获取缓存的读写锁 * @return */ public ReadWriteLock getReadWriteLock() }

假如我们已经完成上述设置就能使用自定义的缓存了

<cache type="com.isyxf.mysql.chapter.MyCache"/>

SQL缓存
决定SQL层面上的缓存规则往往是根据两个属性: useCache 和 flushCache 来完成,其中 useCache 表示是否需要使用缓存,而 flushCache 表示插入后是否需要刷新缓存。

<select ... flushCache="false" useCache="true"/> <insert ... flushCache="true"/> <update ... flushCache="true"/> <delete ... flushCache="true"/>

动态 SQL

MyBatis 的动态 SQL 包括以下几种元素

元素 作用 备注
if 判断语句 单条件分支判断
choose(when、otherwise) 相当于 Java 中的 case when 语句 多条件分支判断
trim(where、set) 辅助元素 用于处理一些 SQL 拼装问题
foreach 循环语句 在 in 语句等列举条件常用
bind 通过 OGML 表达式去自定义一个上下文变量 在进行模糊查询的时候,MySQL 数据库常使用 concat “%” 参数连接,而 Oracle数据库则用 “||”,使用bind就可以屏蔽差异化

扩展阅读