properties 定义配置,配置的属性可以在整个配置文件中的其他位置进行引用
<properties resource="db.properties"></properties>
settings 设置 用于指定Mybatis的一些全局配置属性,改变mybatis的运行时行为
<settings> <!-- 这个配置使全局的映射器启用或禁用 缓存 --> <setting name="cacheEnabled" value="true" /> <!-- 全局启用或禁用延迟加载。当禁用时, 所有关联对象都会即时加载 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 允许或不允许多种结果集从一个单独 的语句中返回(需要适合的驱动) --> <setting name="multipleResultSetsEnabled" value="true" /> <!-- 使用列标签代替列名。 不同的驱动在这 方便表现不同。 参考驱动文档或充分测 试两种方法来决定所使用的驱动 --> <setting name="useColumnLabel" value="true" /> <!-- 允许 JDBC 支持生成的键。 需要适合的 驱动。 如果设置为 true 则这个设置强制 生成的键被使用, 尽管一些驱动拒绝兼 容但仍然有效(比如 Derby) --> <setting name="useGeneratedKeys" value="false" /> <!-- 配置默认的执行器。SIMPLE 执行器没 有什么特别之处。REUSE 执行器重用 预处理语句。BATCH 执行器重用语句 和批量更新 --> <setting name="defaultExecutorType" value="SIMPLE" /> <!-- 设置超时时间, 它决定驱动等待一个数 据库响应的时间 --> <setting name="defaultStatementTimeout" 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类型设置一个别名 ,映射时方便使用 ,分为系统别名 和 自定义别名
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> <typeAlias alias="Comment" type="domain.blog.Comment"/> </typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean对象。
<typeAliases> <!--扫描指定包下的所有实体类--> <package name="com.gw.facade.account.entity"/> <package name="com.gw.facade.account.vo"/> </typeAliases>
typeHandlers 用于jdbcType与javaType之间的转换
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short, short | 数据库兼容的 NUMERIC 或 SHORT INTEGER |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long, long | 数据库兼容的 NUMERIC 或 LONG INTEGER |
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 类型,存储枚举的索引(而不是名称)。 |
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 or LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。
@MappedTypes(Boolean.class) @MappedJdbcTypes(JdbcType.SMALLINT) public class BooleanTypeHandler implements TypeHandler<Boolean>{ public Object getResult(ResultSet arg0, int arg1) throws SQLException { int num = arg0.getInt(arg1); Boolean rt = Boolean.FALSE; if (num == 1){ rt = Boolean.TRUE; } return rt; } public Object getResult(ResultSet arg0, String arg1) throws SQLException { int num = arg0.getInt(arg1); Boolean rt = Boolean.FALSE; if (num == 1){ rt = Boolean.TRUE; } return rt; } public Object getResult(CallableStatement arg0, int arg1) throws SQLException { Boolean b = arg0.getBoolean(arg1); return b == true ? 1 : 0; } public void setParameter(PreparedStatement arg0, int arg1, Boolean arg2,JdbcType arg3) throws SQLException { Boolean b = (Boolean) arg2; int value = (Boolean) b == true ? 1 : 0; arg0.setInt(arg1, value); } }
上面代码中可以按照我们的要求将java的Boolean和jdbc的SMALLINT进行转换,对于这两种数据类型的声明有两种方式:一种是如上在类加上注解进行声明;另外也可以在typeHandler类声明中说明,如下图。
<typeHandlers> <typeHandler javaType="Boolean" jdbcType="SMALLINT" handler="com.gw.common.core.mybatis.BooleanTypeHandler" /> </typeHandlers>
objectFactory mybatis每次创建结果对象的新实例时,它都会使用对象工厂模式去构建pojo
在 MyBatis 中,当其 sql 映射配置文件中的 sql 语句所得到的查询结果,被动态映射到 resultType 或其他处理结果集的参数配置对应的 Java 类型,其中就有 JavaBean 等封装类。而 objectFactory 对象工厂就是用来创建实体对象的类。
在 MyBatis 中,默认的 objectFactory 要做的就是实例化查询结果对应的目标类,有两种方式可以将查询结果的值映射到对应的目标类,一种是通过目标类的默认构造方法,另外一种就是通过目标类的有参构造方法。
有时候在 new 一个新对象(构造方法或者有参构造方法),在得到对象之前需要处理一些逻辑,或者在执行该类的有参构造方法时,在传入参数之前,要对参数进行一些处理,这时就可以创建自己的 objectFactory 来加载该类型的对象。
在这个类中有6个方法:
1⃣️create(Class<T> type):这个方法我认为是创建结果集的方法,但它其实是直接调用了第二个create方法,只不过后两个参数传的是null,所以直接看下面的方法;
2⃣️create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs):这个方法中传了三个参数,分别应该是返回的结果集类型、此类构造函数参数类型、此类构造函数参数值。从它的内部实现来看,首先调用了下面的resolveInterface方法获取返回类型,其次调用instantiateClass方法实例化出我们所需的结果集;
3⃣️setProperties(Properties properties):这个方法是用来设置一些配置信息,比如我们给objectFactory定义一个property子元素时,就是通过这个方法进行配置的;
4⃣️instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs):此方法是用来实例化一个类,需要实例化的类型是通过下面的resolveInterface方法决定,从内部实现来看,这个实例化过程是通过反射实现的;
5⃣️resolveInterface(Class<?> type):此方法是用来对集合类型进行处理,即如果我们定义一个resultType为集合类型,那么它就会根据这个类型决定出即将创建的结果集类型;
6⃣️isCollection(Class<T> type):这个方法是用来判断我们配置的类型是不是一个集合。比如如果返回多条数据,但是我们配置resultType是个普通类,那么在执行过程中就会报错;
以上就是MyBatis默认objectFactory中的具体实现,通过它来创建我们配置的结果集,一般情况下都会使用默认的对象工厂,但是我们也可以自定义一个,只要继承DefaultObjectFactory.java即可。
plugins 插件 mybatis 允许在已映射的语句执行过程中的某一点进行拦截调用
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
只需实现Interceptor接口同时指明需要拦截的方法签名,并在mybatis的配置文件中声明该签名:
@Intercepts({ @Signature (type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class } ) }) public class ExecutorInterceptor extends AbstractInterceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
<!-- mybatis-config.xml配置 --> <plugins> <plugin interceptor="com.gw.common.core.mybatis.interceptor.ExecutorInterceptor"> </plugin> </plugins>
mappers 配置引入映射器的方法 可以使用相对路径的资源引用 或完全限定资源定位符(包括file://URL) 或类名和包名等
<mappers>
<!--直接映射到相应的mapper文件 -->
<mapper resource="mapper/userMapper.xml"/>
<!--通过类扫描mapper文件-->
<mapper class="cn.qin.mapper.userMapper"/>
<!--扫描包下所有的mapper文件-->
<package name="cn.qin.mapper"/>
</mappers>
environments 用于配置多个数据源 ,每个数据源分为数据库源和事务的配置
<configuration>
<!--引入外部资源 -->
<properties resource="./mybatis-mysql.properties">
</properties>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<objectFactory type="com.zzz.mybatis.object.MyObjectFacotry">
<property name="env" value="test"/>
</objectFactory>
<!--设置默认的环境为开发环境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="UNPOOLED">
<property name="driver" value="${dev.driver}"/>
<property name="url" value="${dev.url}"/>
<property name="username" value="${dev.username}"/>
<property name="password" value="${dev.password}"/>
</dataSource>
</environment>
<!--测试环境用 -->
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${test.driver}"/>
<property name="url" value="${test.url}"/>
<property name="username" value="${test.username}"/>
<property name="password" value="${test.password}"/>
</dataSource>
</environment>
<!--生产环境用 -->
<environment id="prod">
<transactionManager type="MANAGED"/>
<dataSource type="JDBC">
<property name="driver" value="${prod.driver}"/>
<property name="url" value="${prod.url}"/>
<property name="username" value="${prod.username}"/>
<property name="password" value="${prod.password}"/>
</dataSource>
</environment>
</environments>
</configuration>
databaseldProvider 根据不同数据库厂商执行不同的语句,用于一个系统内多个厂商数据源支持
<databaseIdProvider type="DB_VENDOR"> <property name="MySQL" value="mysql" /> <property name="Oracle" value="oracle" /> </databaseIdProvider>
<select id="SelectTime" resultType="String" databaseId="mysql"> SELECT NOW() FROM dual </select> <select id="SelectTime" resultType="String" databaseId="oracle"> SELECT 'oralce'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') FROM dual </select>