Mybatis之配置详解
Mybatis系列文章
Mybatis之配置详解
Mybatis之XML 映射器详解
Mybatis之动态 SQL详解
Mybatis之缓存详解
前言
以下描述的配置标签,均以xml配置标签为主,即mybatis-config.xml配置文件里的标签,不过多介绍通过application.yml来进行配置,因为两者配置是等价的,这里推荐将mybatis配置集中配置在mybatis-config.xml中。
配置目录结构如下:
属性(properties)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java properties属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。比如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取SqlSessionFactoryBuilder.build方法参数传递的属性,并覆盖之前读取过的同名属性。
从 MyBatis 3.4.2
开始,你可以为占位符指定一个默认值
。例如:
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${username:ut_user}"/>
<!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 'ut_user' -->
</dataSource>
这个特性默认是关闭的。要启用这个特性,需要添加一个特定的属性来开启这个特性。例如:
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
<!-- 启用默认值特性 -->
</properties>
注意:启用默认值特性 仅对configuration、SQL中${}占位符有用
提示
如果你在属性名中使用了 “:” 字符(如:db:username),或者在 SQL 映射中使用了 OGNL 表达式的三元运算符(如: ${tableName != null ? tableName : ‘global_constants’}),就需要设置特定的属性来修改分隔属性名和默认值的字符。例如:
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/>
<!-- 修改默认值的分隔符 -->
</properties>
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${db:username?:ut_user}"/>
</dataSource>
设置(settings)
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true | false | false |
aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。 | true | false | false (在 3.4.1 及之前的版本中默认为 true) |
multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志(‘org.apache.ibatis.session.AutoMappingUnknownColumnBehavior’ 的日志等级必须设置为 WARN)FAILING: 映射失败 (抛出 SqlSessionException) | NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
defaultResultSetType | 指定语句默认的滚动策略。 | (新增于 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE| SCROLL_INSENSITIVE| DEFAULT(等同于未设置) | 未设置 (null) |
safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true | false | False |
safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。 | (新增于 3.4.5) 一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。 | (新增于 3.4.2) true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。 | (新增于 3.4.1) true | false | true |
configurationFactory | 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。 | (新增于 3.2.3) 一个类型别名或完全限定类名。 | 未设置 |
一个推荐的 settings 元素的示例如下:
<settings>
<!--是否开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
<!--自动映射列到字段或属性的行为 PARTIAL 只会自动映射没有定义嵌套结果映射的字段-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!--发现自动映射目标未知列(或未知属性类型)的行为 NONE: 不做任何反应-->
<setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
<!--配置默认的执行器-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!--一级缓存 STATEMENT使一级缓存不起作用-->
<setting name="localCacheScope" value="SESSION"/>
<!--空值的默认 JDBC 类型-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!--指定 Enum 使用的默认 TypeHandler-->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<!--非默认值,设置驼峰匹配-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--控制台打印 可打印sql入参出参-->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例-->
<setting name="returnInstanceForEmptyRow" value="false" />
</settings>
关于Mybatis延迟加载
Mybatis的延迟加载主要针对于嵌套select查询,在配置文件中通过两个属性lazyLoadingEnabled
和aggressiveLazyLoading
来控制延迟加载
和按需加载
。
lazyLoadingEnabled
:是否启用延迟加载,mybatis默认为false,不启用延迟加载。lazyLoadingEnabled
属性控制全局是否使用延迟加载,特殊关联关系也可以通过嵌套查询中fetchType
属性单独配置(fetchType属性值lazy或者eager)。
aggressiveLazyLoading
:是否按需加载属性,默认值false,启用该属性并且lazyLoadingEnabled
属性启用时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载,使用到某关联属性时,实时执行嵌套查询加载该属性。
类型别名(typeAliases)
- 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
- 指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的非限定类名来作为它的别名。 若有注解,则别名为其注解值。见下面的例子:
@Alias("author")
public class Author {
...
}
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
类型处理器(typeHandlers)
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
提示
从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short, short | 数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long, long | 数据库兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler | java.lang.Float, float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double, double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB, LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR, NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB, LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler
接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler
, 并且可以(可选地)将它映射到一个 JDBC 类型。比如:
package com.nestor.mybatisdemo.typehandler;
/**
* 年级枚举类型处理器
*
* @author : Nestor.Bian
* @version : V 1.0
* @date : 2020/3/22
*/
@MappedTypes(GradeLevel.class)
@MappedJdbcTypes(value = JdbcType.TINYINT, includeNullJdbcType = true)
public class GradeLevelTypeHandler extends BaseTypeHandler<GradeLevel> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, GradeLevel level, JdbcType jdbcType) throws SQLException {
System.err.println(String.format("level: %s", level));
preparedStatement.setInt(i, level.getValue());
}
@Override
public GradeLevel getNullableResult(ResultSet resultSet, String s) throws SQLException {
return EnumUtil.getByCode(resultSet.getInt(s), GradeLevel.class);
}
@Override
public GradeLevel getNullableResult(ResultSet resultSet, int i) throws SQLException {
return EnumUtil.getByCode(resultSet.getInt(i), GradeLevel.class);
}
@Override
public GradeLevel getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return EnumUtil.getByCode(callableStatement.getInt(i), GradeLevel.class);
}
}
mybatis-config.xml
<!--定义类型处理器-->
<typeHandlers>
<typeHandler handler="com.nestor.mybatisdemo.anothertypehandler.BaseEnumTypeHandler"/>
<package name="com.nestor.mybatisdemo.typehandler" />
</typeHandlers>
- 如上配置Mybatis会自动隐式的调用,不需要显示地在入参和结果集处显式的调用typeHandler=…。
- 如果显式指定将会忽略类型,直接使用指定的类型处理器处理。
最好明确指定@MappedJdbcTypes
和@MappedTypes
来让Mybatis知道处理哪个类型,否则可能导致误用。 - 不明确指定
@MappedTypes
可以通过类型处理器的泛型,得知该类型处理器处理的 Java 类型。 - 当在 ResultMap 中决定使用哪种类型处理器时,此时 Java 类型是已知的(从结果类型中获得),但是 JDBC 类型是未知的。 因此 Mybatis 使用 javaType=[Java 类型], jdbcType=null 的组合来选择一个类型处理器。 这意味着使用 @MappedJdbcTypes 注解可以限制类型处理器的作用范围,并且可以确保,除非显式地设置,否则类型处理器在 ResultMap 中将不会生效。 如果希望能在 ResultMap 中隐式地使用类型处理器,那么设置
@MappedJdbcTypes
注解的includeNullJdbcType=true
即可。 然而从Mybatis 3.4.0
开始,如果某个 Java 类型只有一个注册的类型处理器,即使没有设置 includeNullJdbcType=true,那么这个类型处理器也会是 ResultMap 使用 Java 类型时的默认处理器。
你可以创建能够处理多个类的泛型类型处理器。为了使用泛型类型处理器, 需要增加一个接受该类的 class 作为参数的构造器,具体代码如下:
/**
* BaseEnum枚举类型处理器
*
* @author : Nestor.Bian
* @version : V 1.0
* @date : 2020/3/22
*/
@MappedTypes({GradeLevel.class, Sex.class})
@MappedJdbcTypes(value = {JdbcType.VARCHAR, JdbcType.TINYINT}, includeNullJdbcType = true)
public class BaseEnumTypeHandler<T extends BaseEnum> extends BaseTypeHandler<T> {
private Class<T> type;
public BaseEnumTypeHandler(Class<T> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
} else {
this.type = type;
}
}
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {
preparedStatement.setObject(i, t.getValue());
}
@Override
public T getNullableResult(ResultSet resultSet, String s) throws SQLException {
return (T) EnumUtil.getByCode(resultSet.getObject(s), type);
}
@Override
public T getNullableResult(ResultSet resultSet, int i) throws SQLException {
return (T) EnumUtil.getByCode(resultSet.getObject(i), type);
}
@Override
public T getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return (T) EnumUtil.getByCode(callableStatement.getObject(i), type);
}
}
注意:泛型类型处理器必须明确指定@MappedTypes,来指定明确处理那些java类型
插件(plugins)
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。 如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。 这些都是更底层的类和方法,所以使用插件的时候要特别当心。
/**
* 自定义Mybatis拦截器
*
* @author : Nestor.Bian
* @version : V 1.0
* @date : 2020/3/22
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "queryCursor", args = {MappedStatement.class, Object.class,
RowBounds.class}),
})
public class CustomMybatisInterceptor implements Interceptor {
private Properties properties;
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.err.println("拦截前参数:" + Arrays.toString(invocation.getArgs()));
Object result = invocation.proceed();
System.err.println("拦截后结果:" + result);
return result;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
}
mybatis-config.xml
<!--定义插件-->
<plugins>
<plugin interceptor="com.nestor.mybatisdemo.common.CustomMybatisInterceptor"></plugin>
</plugins>
数据库厂商标识(databaseIdProvider)
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:
<databaseIdProvider type="DB_VENDOR" />
databaseIdProvider 对应的 DB_VENDOR 实现会将 databaseId 设置为 DatabaseMetaData#getDatabaseProductName() 返回的字符串。 由于通常情况下这些字符串都非常长,而且相同产品的不同版本会返回不同的值,你可能想通过设置属性别名来使其变短:
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-demo?useUniCode=true&characterEncoding=utf-8&serverTimezone=UTC" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
在提供了属性别名时,databaseIdProvider 的 DB_VENDOR
(对应Java类VendorDatabaseIdProvider
) 实现会将 databaseId 设置为数据库产品名与属性中的名称第一个相匹配的值,如果没有匹配的属性,将会设置为 “null”
。 在这个例子中,如果 getDatabaseProductName()
返回“Oracle (DataDirect)”,databaseId 将被设置为“oracle”。
你可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider
并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider:
/**
* 自定义databaseId provider
*
* @author : Nestor.Bian
* @version : V 1.0
* @date : 2020/4/18
*/
public class CustomDatabaseIdProvider implements DatabaseIdProvider {
private static final String DATABASE_MYSQL = "MySQL";
private static final String DATABASE_POSTGRESQL = "PostgreSQL";
private static final String DATABASE_ORACLE = "Oracle";
private static final String DATABASE_DB2 = "DB2";
@Override
public void setProperties(Properties p) {
}
@Override
public String getDatabaseId(DataSource dataSource) throws SQLException {
Connection conn = dataSource.getConnection();
String dbName = conn.getMetaData().getDatabaseProductName();
String dbAlias = "";
switch (dbName) {
case DATABASE_MYSQL:
dbAlias = "mysql";
break;
case DATABASE_POSTGRESQL:
dbAlias = "pg";
break;
case DATABASE_ORACLE:
dbAlias = "oracle";
break;
case DATABASE_DB2:
dbAlias = "db2";
break;
default:
break;
}
return dbAlias;
}
}
mybatis-config.xml中添加如下配置:
<!--使用自定义DatabaseIdProvider-->
<databaseIdProvider type="com.nestor.mybatisdemo.common.CustomDatabaseIdProvider" />
映射器(mappers)
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
映射器接口扫描
@SpringBootApplication
@MapperScan("com.nestor.mybatisdemo.mapper")
@EnableTransactionManagement
public class MybatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisDemoApplication.class, args);
}
}
在App启动类上添加@MapperScan
配置需要扫描的包即可,如果不在扫描包的范围内,可以在mapper接口上加@Mapper
接口,同样能被扫描到。
github工程地址:https://github.com/nestorbian/spring-boot-examples/tree/master/mybatis-demo
Mybatis系列文章
Mybatis之配置详解
Mybatis之XML 映射器详解
Mybatis之动态 SQL详解
Mybatis之缓存详解
参考:
Mybatis学习系列延迟加载
Mybatis3官网
MyBatis配置文件(八)--databaseIdProvider数据库厂商标识