本文参考官网:https://mybatis.org/mybatis-3/zh/configuration.html
配置文件结构如下
properties
这些属性可以在外部进行配置,并可以进行动态替换。如配置数据源的时候可以${xxx}
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
从 MyBatis 3.4.2 开始,你可以为占位符指定一个默认值,如
${username:ut_user}<!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 'ut_user' -->
settings
会改变 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 类型设置一个缩写名字。意在降低冗余的全限定类名书写
typeHandlers
设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。
你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler
接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler
, 并且可以(可选地)将它映射到一个 JDBC 类型。
get 是 jdbc变java set 是 java 变jdbc
objectFactory
每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现(可以继承DefaultObjectFactory)。
当我们把数据库返回的结果集转换为实体集,需要创建对象的实例,由于不知道需要处理的类型是什么,有哪些属性,不能new,只能通过反射
注:objectFactory.create()什么时候调用?
创建DefaultResultSetHandler和创建对象的时候会调用objectFactory.create();
创建对象后,已有的属性为什么被覆盖?
DefaultResultSetHandler的getRowValue()调用了applyPropertyMappings()
在返回结果的时候ObjectFactory和TypeHandler哪个先工作?
先创建对象,所以是ObjectFactory
PS:step out可以看到一步步调用层级。
plugins
拦截4大对象
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
注:SqlSession是对外提供的接口,其中的方法是由Executor完成(DefaultSqlSession中可以看到),而SQL的执行按照过程,分为ParameterHandler处理参数,StatementHandler执行SQL,ResultSetHandler处理结果
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
public Object intercept(Invocation invocation) throws Throwable {
// implement pre processing if need
Object returnObject = invocation.proceed();
// implement post processing if need
return returnObject;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
environments
每个数据库对应一个 SqlSessionFactory 实例,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例。为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
事务管理器(transactionManager)
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
使用这Transaction 和TransactionFactory 接口,可以完全自定义 MyBatis 对事务的处理。
数据源(dataSource)
- UNPOOLED
- POOLED
- JNDI
数据库厂商标识(databaseIdProvider)
可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider
并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider:
映射器(mappers)
定义 SQL 映射语句。使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等告诉 MyBatis 到哪里去找映射文件