参考
- MyBatis官方XML配置中文说明 http://www.mybatis.org/mybatis-3/zh/configuration.html#properties
1. 配置顺序
configuration(配置顺序)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
2. 属性(properties)
2.1. 定义属性
在 <properties> 内部可以通过 <propertie> 定义key/value,然后通过${var} 来引用属性
1 | <properties> |
2.2. 引用外部配置文件
外部配置文件 jdbc.properties 的内容如下:1
2
3
4jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=true
jdbc.username=root
jdbc.password=123456
<properties> 的 resource 属性 可以引用classpath下的配置文件
1 | <properties resource="jdbc.properties" /> |
<properties> 的 url 属性 可以引用网络中的配置文件,包括本地磁盘中的配置文件
1 | <properties url="file:///c:/jdbc.properties" /> |
引用外部配置文件,和直接定义属性,二者可以结合起来。配置加载顺序遵循就近原则。先加载外部,再加载内部。若有冲突,则内部会覆盖外部同名配置1
2
3
4
5
6
7
8<!-- resource引用配置文件 -->
<properties resource="file1.properties">
<!-- 直接定义属性 -->
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/test?useSSL=true"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>
3. 设置(settings)
settings 是MyBatis中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
详细说明可以参考官方文档 http://www.mybatis.org/mybatis-3/zh/configuration.html#settings ,下面列举一些常用的配置
3.1. mapUnderscoreToCamelCase
凡是使用Mybatis,一般都要设置mapUnderscoreToCamelCase为true1
2
3
4
5
6<!-- mapUnderscoreToCamelCase
描述:是否开启自动驼峰命名规则(camel case)映射,
即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射
有效值:true | false
默认值:false -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
4. 类型别名(typeAliases)
typeAliases可以给Java数据类型起一个别名,存在的意义仅在于用来减少类完全限定名的冗余
但是在实际开发中,不推荐使用typeAliases,而是推荐直接使用全类名。使用全类名的好处是,你可以很清晰地看出,这个类型属于哪个包。而且使用全类名,在IDE中,可以通过CTRL+左键直接定位到对应的类,便于查看
4.1. typeAlias起别名
1 | <typeAliases> |
在SQL映射文件中,都可以用别名替代全类名1
2
3
4<!-- resultType的值本来要写"demo.mybatis.entity.Person",现在就可以用别名简写了 -->
<select id="findById" resultType="Person">
SELECT * FROM person WHERE person_id = #{personId}
</select>
需要注意的是,别名的使用是不区分大小写的。例如你给demo.mybatis.entity.Person设置别名为person,引用别名时,Person、perSON等等都是等价的
1 | <!-- 使用PERSON也是可以的 --> |
4.2. package批量起别名
假如有很多个类,你都想起别名,一个一个设置别名就会很累,此时可以使用<package>,mybatis会自动扫描该包及其子包(递归扫描)所有的类,将简单类名作为别名。
需要注意,这里的别名仍是不区分大小写的
1 | <typeAliases> |
4.3. 内置别名
MyBatis已经给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 |
5. 类型处理器(typeHandlers)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的SQL类型的值以合适的方式转换成 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 |
6. 对象工厂(objectFactory)
MyBatis查询得到一条记录,将数据封装到对象中,这个对象就是通过objectFactory来创建的。
MyBatis底层有一个默认的对象工厂,来实例化对象。如果你有额外的需求,可以自己写一个对象工厂。但是实际开发中没有重写的必要
7. 插件(plugins)
插件是MyBatis提供的一个非常强大的机制,我们可以通过插件来修改MyBatis的一些核心行为。插件通过动态代理机制,可以介入四大对象的任何一个方法的执行
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
8. 环境配置(environments)
环境配置就是指配置事务管理器和数据源,每一个环境environment就对应一个transactionManager和dataSource
你可以配置多个环境,如开发是连接数据库A,测试时连接数据库。通过<environments>的default属性,来决定当前SqlSessionFactory实例选择哪个环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
1 | <!-- default指定当前使用哪个环境配置 --> |
transactionManager是配置事务管理器的,不需要深研。因为Spring的事务管理机制更加强大,实际开发时是使用Spring来管理事务,MyBatis只要知道就这么个东西就可以了
dataSource配置数据源,就是配置连接数据库的一些参数。实际开发时,数据源也是交给Spring管理的,MyBatis只负责CRUD
9. 数据库厂商标识(databaseIdProvider)
Hibernate的数据库移植性非常强,因为所有的SQL都是框架自动生成的。例如项目的数据库从MySQL移植到Oracle,Hibernate会自动检测,在执行时会转为生成Oracle的SQL语句。
但是MyBatis的移植性就没有那么好,因为SQL都是你亲自去写的。如果项目的数据库从MySQL移植到Oracle,你原来的SQL都是针对MySQL的,就会导致项目无法运行。MyBatis考虑到这一情况,就有了databaseIdProvider这一机制。
你可以在全局配置中添加databaseIdProvider1
2
3
4
5
6
7
8
9
10
11
12<!-- type="DB_VENDOR"是固定的写法 -->
<databaseIdProvider type="DB_VENDOR">
<!--
name: 数据库厂商的标识,这些标识的值都是固定的,
你可以通过JDBC的Connection的getDatabaseProductName()来获取
value: 给这个标识起一个好用的名字 -->
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
<property name="MySQL" value="mysql" />
<property name="SQL Server" value="sqlserver" />
</databaseIdProvider>
在写SQL映射文件时,可以根据数据库环境来执行对应的SQL语句。如果匹配到databaseId,则执行对应的SQL,如果匹配不到,则执行没有databaseId的那个SQL1
2
3
4
5
6
7
8
9
10
11
12<!-- 如果连接的是Oracle,则执行该语句 -->
<select id="findById" resultType="demo.mybatis.entity.Person" databaseId="oracle">
SELECT * FROM person WHERE person_id = #{personId}
</select>
<!-- 如果连接的是MySQL,则执行该语句 -->
<select id="findById" resultType="demo.mybatis.entity.Person" databaseId="mysql">
SELECT * FROM person WHERE person_id = #{personId}
</select>
<!-- 如果连接的是其它数据库,则执行该语句 -->
<select id="findById" resultType="demo.mybatis.entity.Person">
SELECT * FROM person WHERE person_id = #{personId}
</select>
10. 映射器(mappers)
你写了一些SQL映射文件,MyBatis默认是不知道这些配置文件在哪里的。<mappers>的作用就是告诉MyBatis到哪里去找这些SQL映射文件
10.1. resource使用类路径注册
resources是在类路径下找对应的SQL映射文件
1 | <mappers> |
10.2. url指定网络地址注册
url给出SQL映射文件的网络地址,包括本地路径。在实际开发时,该方式不可取1
2
3
4
5
6
7<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<!-- Linux路径 -->
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<!-- Windows路径 -->
<mapper url="file:///c:/User.xml" />
</mappers>
10.3. class指定Mapper接口实现注册
class给出指定Mapper接口的全类名。但是光指定Mapper接口,MyBatis怎么知道SQL映射文件在哪里呢?
原因是,在使用class属性时,MyBatis默认认为SQL映射文件被要求放在与对应Mapper接口同一路径下,且名称必须要求。例如UserMapper接口,对应的SQL映射文件名就是UserMapper.xml,也两个文件必须放在同一路径下
1 | <mappers> |
10.4. package包扫描注册
package是class方式的扩展。<package>会扫描指定包及其子包下所有的Mapper接口,并找到同一路径下的SQL映射文件。且要求SQL映射文件的名称与Mapper接口的名称必须相同
1 | <mappers> |
注意:实际项目就使用package方式引入映射文件,最方便。而且项目中很可能是基于MyBatis的注解驱动和XML混合开发,SQL映射文件可能就直接被省略了,resource/url的方式直接变得不可用了。此时只能选择class/package方式