MyBatis 配置详解
properties 元素
是一种配置属性的元素,让我们在配置文件的上下文中使用这些配置
property 子元素定义配置
1 <properties> 2 <property name="driver" value="驱动" /> 3 <property name="url" value="jdbc连接" /> 4 <property name="username" value="数据库用户名" /> 5 <property name="password" value="数据库密码" /> 6 </properties>
使用配置文件
<properties resource="db.properties"></properties>
配置的优先级
- 在proerties元素体内指定的属性首先被读取
- 根据properties元素中的resource属性读取类路径下属性文件,或者根据url属性指定的路径读取属性文件,并覆盖已读取的同名属性
- 读取作为方法参数传递的属性,并覆盖已读取的同名属性
建议:不要使用混合的方式,这样会使得管理混乱,首选的方式是使用properties
设置 - settings
在settings中的配置会改变 MyBatis的运行时行为,即使不配置 settings,MyBatis也可以正常工作
建议:在使用时不需要全部都配置,按需配置即可
<settings> <!-- 缓存的全局开关 --> <setting name="cacheEnabled" value="true"/> <!-- 延迟加载的全局开关,开启时,所有关联对象都会延迟加载,特定关联关系时设置fetchType来覆盖该项的开关状态 --> <setting name="lazyLoadingEnabled" value="false"/> <!-- 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载,反之,每种属性将会按需加载 --> <setting name="aggressiveLazyLoading" value="true"/> <!-- 是否允许单一语句返回多结果集(需要驱动兼容) --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 使用标签代替列名(不同驱动的表现不同) --> <setting name="useColumnLabel" value="true"/> <!-- 允许JDBC支持自动生成主键(需要驱动兼容,设置为true,强制使用自动生成的主键) --> <setting name="useGeneratedKeys" value="false"/> <!-- 指定Mybatis如何自动映射列到字段或属性 NONE:取消自动映射 PARTIAL:只会自动映射没有定义嵌套结果集映射的结果集 FULL:自动映射任意复杂的结果集(无论是否嵌套),在性能上会下降 --> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 配置默认的执行器 SIMPLE:普通的执行器,在insert、update、delete中,成功返回条数,失败返回0 REUSE:执行器会重用预处理语句(prepared statements),缓存同一个sql的statement,优化性能 BATCH:执行器将重用语句并执行批量更新,insert、update、delete返回值将无任何意义 --> <setting name="defaultExecutorType" value="SIMPLE"/> <!-- 设置等待数据库响应的秒数,未配置时这个值是驱动默认的时间 --> <setting name="defaultStatementTimeout" value="25"/> <!-- 允许在嵌套语句中使用分页 --> <setting name="safeRowBoundEnabled" value="false"/> <!-- 是否开启自动驼峰命名映射(小驼峰) --> <setting name="mapUnderscoreToCamelCase" value="false"/> <!-- 利用本地缓存机制防止循环引用和加速重复嵌套查询 SESSION: 缓存一个会话中执行的所有查询 STATEMENT:本地会话仅作用在语句执行上,对相同SqlSession的不同调用将不会共享数据 --> <setting name="localCacheScope" value="SESSION"/> <!-- 当参数没有设置 jdbcType 时,为空值(数据库NULL)指定 jdbcType 的类型 详细类型参考 jdbcType ,常用 NULL、VARCHAR、OTHER 默认为 OTHER --> <setting name="jdbcTypeForNull" value="OTHER"/> <!-- 指定对象的方法触发一次延迟加载,多个方法使用逗号分隔 --> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> <!-- 指定动态SQL生成的默认语言,一般不配置 --> <setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver"/> <!-- 指定当结果集中值为null的时候,是否调用映射对象的setter方法(map对象则调用put) 注意:主要基本类型(int、boolean)不能设置为null --> <setting name="callSettersOnNulls" value="false"/> <!-- 指定Mybatis追到日志的前缀名称,值可以是任何字符串 --> <setting name="logPrefix" value=""/> <!-- 指定MyBatis所用日志的具体实现,未指定则自动进行查找 SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING --> <setting name="logImpl" value=""/> <!-- 指定MyBatis创建具有延迟加载能力的对象所使用到的代理工具 CGLIB、JAVASSIST 默认值比较特殊,版本3.3.0(含)以上使用JAVASSIST否则CGLIB --> <setting name="proxyFactory" value=""/> </settings>
别名 - typeAliases
别名是一个指代的名称,有时候遇到类全限定名过长,所以我们希望用一个简短的名称去指代它,而这个名称可以在MyBatis上下文中使用
例如: 某个类的全限定名为 java.lang.Object, 我们使用 typeAliases 功能定义 object 去指代 java.lang.Object, 之后在Mybatis中想要使用
java.lang.Object 的地方直接写 object 即可。
注意: 别名不区分大小写
为了减少重复生成typeAliases的实例,别名长期保存在 Configuration 对象中
系统定义别名
可以在 org.apache.ibatis.type.TypeAliasRegistry 看到系统自定义注册的别名
| 别名 | 映射类型 | 支持数组 |
| _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 | 否 |
| ResultSet | ResultSet | 否 |
自定义别名
在配置文件中自定义别名
<typeAliases> <typeAlias alias="object" type="java.lang.Object" /> </typeAliases>
在配置文件中使用扫描包的方式自定义别名
注意: 默认类名就是别名,别名不支持自定义,别名不区分大小写
<typeAliases> <package name="com.banywl.my.entity"/> <package name="com.banywl.my.module"/> <package name="com.banywl.my.pojo"/> </typeAliases>
使用@Alias注解配合扫描包的方式自定义别名
注意: 包扫描的方式帮我们减轻别名注册的工作量,@Alias 实现了别名的个性化,仅使用@Alias是不会注册别名的
import org.apache.ibatis.type.Alias; @Alias("animal") public class Animal { public String name; public Animal() { } // getter,setter.... }
类型处理器 - typeHandler
MyBatis 在处理执行SQL的参数时或者从数据返回的结果集中取出一个值时,都会使用注册了的typeHandler进行处理
在处理参数时,将java数据类型通过typeHandler处理为不同的数据库数据类型
在处理数据库返回结果时,将不同的数据库结果集中的值的类型通过typeHandler处理为java对应的类型
注意:
- 数值类型的精度,数据库 int、double、decimal类型与java的精度、长度是不一样的
- 时间精度, 只获取日期部分用DateOnlyTypeHandler 即可,用精度为秒的使用SqlTimestampTypeHandler
org.apache.ibatis.type 包下可以查看TypeHandler类
系统定义typeHandler
| 类型处理器 | 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 |
| ClobTypeHandler | java.lang.String | CLOB, LONGVARCHAR |
| NStringTypeHandler | java.lang.String | NVARCHAR, NCHAR |
| NClobTypeHandler | java.lang.String | NCLOB |
| 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类型,存储枚举的索引(而不是名称) |
自定义typeHandler
<typeHandlers> <typeHandler jdbcType="VARCHAR" javaType="string" handler="com.test.MyStringHandler" /> </typeHandlers>
1 package com.test; 2 3 import org.apache.ibatis.type.JdbcType; 4 import org.apache.ibatis.type.MappedJdbcTypes; 5 import org.apache.ibatis.type.MappedTypes; 6 import org.apache.ibatis.type.TypeHandler; 7 8 import java.sql.CallableStatement; 9 import java.sql.PreparedStatement; 10 import java.sql.ResultSet; 11 import java.sql.SQLException; 12 13 @MappedTypes({String.class}) // 定义的JavaType类型,指定哪些Java类型被拦截 14 @MappedJdbcTypes(JdbcType.VARCHAR) // 定义的是JdbcType 类型,他满足枚举类 org.apache.ibatis.type.JdbcType 所列的枚举类型 15 public class MyStringHandler implements TypeHandler<String> { 16 17 18 public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { 19 // 设置String 参数 20 ps.setString(i,parameter); 21 } 22 23 public String getResult(ResultSet rs, String columnName) throws SQLException { 24 // 从指定列名获取字符串 25 return rs.getString(columnName); 26 } 27 28 public String getResult(ResultSet rs, int columnIndex) throws SQLException { 29 // 从指定列索引获取字符串 30 return rs.getString(columnIndex); 31 } 32 33 public String getResult(CallableStatement cs, int columnIndex) throws SQLException { 34 // 从存储过程返回的结果集中获取columnIndex处的字符串 35 return cs.getString(columnIndex); 36 } 37 }
然后再 result 中指定MyStringHndler
<resultMap type="user" id="baseMap"> <id column="id" property="id" javaType="long" jdbcType="BIGINT" /> <result column="uname" property="uname" typeHandler="com.test.MyStringHandler" /> </result>
通过扫描批量注册typeHandler
<typeHandlers> <package name="com.test"/> </typeHandlers>
枚举类型的typeHandler
- EnumTypeHandler , 存储枚举的 id
- EnumOrdinalTypeHandler,存储枚举的name
使用的比较少
public enum Sex { UNKNOWN(0,"保密"),MALE(1,"男"),FEMALE(2,"女"); private int id; private String name; Sex(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static Sex getSex(int id){ switch (id){ case 1: return MALE; case 2: return FEMALE; default: return UNKNOWN; } } }
ObjectFactory
当MyBatis 在构建一个结果返回的时候,都会使用ObjectFactory去构建POJO
默认的ObjectFactory: org.apache.ibatis.reflection.factory.DefaultObjectFactory
设置自定义ObjectFactory
用默认的即可,一般不需要自定义ObjectFactory
<objectFactory type="com.test.MyObjectFactory"> <property name="name" value="MyObjectFactory"/> </objectFactory>
1 package com.test; 2 import org.apache.ibatis.reflection.factory.DefaultObjectFactory; 3 4 import java.util.List; 5 import java.util.Properties; 6 7 public class MyObjectFactory extends DefaultObjectFactory { 8 9 @Override 10 public <T> T create(Class<T> type) { 11 // 使用工厂模式创建对象 12 return super.create(type); 13 } 14 15 @Override 16 public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { 17 // 使用工厂模式创建对象,对象类型,构造参数类型列表,构造参数值 18 return super.create(type, constructorArgTypes, constructorArgs); 19 } 20 21 @Override 22 public <T> boolean isCollection(Class<T> type) { 23 return super.isCollection(type); 24 } 25 26 public void setProperties(Properties properties) { 27 // 定制属性 28 super.setProperties(properties); 29 } 30 }
插件配置
<plugins> <!-- interceptor 配置插件类 --> <plugin interceptor="com.test.plugin.MyPlugin"> <!-- 插件的初始化属性 --> <property name="aname" value="unknown"/> </plugin> </plugins>
配置环境 - environments
配置环境可以注册多个数据源,每个数据源分为两大部分: 数据源配置和数据库事务配置
<!-- default 标明启用哪个数据源配置 --> <environments default="development"> <environment id="development"> <!-- type 分为 JDBC(JDBC事务管理方式)、MANAGED(容器方式管理事务、JNDI)、自定义、 --> <transactionManager type="JDBC"> <!-- 事务不自动提交 --> <property name="autoCommit" value="false"/> </transactionManager> <!-- 配置数据源信息 type 分为4种: UNPOOLED,非连接池数据库 POOLED,连接池数据库 JNDI数据源, 自定义数据源 --> <dataSource type="POOLED"> <property name="driver" value=""/> <property name="url" value=""/> <property name="username" value=""/> <property name="password" value=""/> </dataSource> </environment> </environments>
数据库厂商标识 - databaseIdProvider
绝大多数情况下不会用到这个配置
这个配置用来设定,在MyBatis配置了多数据源时并不是使用同一种数据库管理系统,例如三个数据源,对应数据库系统mysql、DB2、Oracle
系统默认规则
<databaseIdProvider type="DB_VENDOR"> <property name="SQL SERVER" value="sqlserver"/> <property name="MySQL" value="mysql"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle"/> </databaseIdProvider>
如何使用?
<select id="countUser" resultType="long" databaseId="mysql"> select count(*) from user; </select>
如果没有配置 databaseIdProvider,那么database就会返回null
如果配置了databaseIdProvider,那么mybatis就会根据name去匹配数据库信息,如果匹配的上就设置databseId信息,否则为null
如果Configuration的databaseId不为空,则他会找到配置databseId的SQL语句
MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句,如果同时找到带有databseId和不带databseId的语句,则会舍弃后者
自定义databaseIdProvider参考: org.apache.ibatis.mapping.DatabaseIdProvider
引入映射器
文件路径引入
<mappers> <!-- 相对于项目目录 --> <mapper resource="com/test/mapper/UserMapper.xml" /> <!-- 绝对路径 --> <mapper url="file:///root/documents/mybatis/src/java/com/test/mapper/UserMapper.xml" /> </mappers>
包名引入
<mappers> <package name="com.test.mapper"/> </mappers>
类注册引入
<mappers> <mapper class="com.test.mapper.UserMapper" /> </mappers>

浙公网安备 33010602011771号