[SSM][4][MyBatis配置]

第4章 MyBatis配置

4.1 概述

MyBatis配置文件中所有元素清单如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<? xml version="1.0" encoding="UTF-8"?>
<configuration>
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型命名-->
<typeHandlers><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment><!--环境变量-->
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
<environments>
<databaseIdProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configuration>

MyBatis配置项的顺序不能颠倒,否则在启动阶段会发生异常

4.2 properties属性

properties属性可以给系统配置一些运行参数,可以放在XML文件中,便于参数修改

MyBatis提供3种方式来使用properties

  • property子元素
  • properties文件
  • 程序代码传递

4.2.1 property子元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="database.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="database.url" value="jdbc:mysql://localhost:3306/mybatisdemo?serverTimezone=UTC"/>
<property name="database.username" value="root"/>
<property name="database.password" value="123456"/>
</properties>
<typeAliases>
<typeAlias type="MyBatisDemo.pojo.Role" alias="role"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="MybatisDemo/mapper/RoleMapper.xml"/>
</mappers>
</configuration>

这里使用了元素<properties>下的子元素<property>定义,用字符串database.username定义数据库用户名,然后就可以在数据库定义中引入这个已经定义好的属性参数,如${database.username},这样可以定义一次到处引用

4.2.2 使用properties文件

我们可以配置多个键值放在一个properties文件中,也可以把多个键值放到多个properties文件中。

先定义文件jdbc.properties

1
2
3
4
database.driver=com.mysql.cj.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/mybatisdemo?serverTimezone=UTC
database.username=root
database.password=123456

然后在mybatis中通过<properties>的属性resource来引入这个文件

1
<properties resource="jdbc.properties"/>

4.2.3 使用程序传递方式传递参数

4.2.4 总结

这三种方式是具有优先级顺序的,MyBatis会根据优先级来覆盖原先配置的属性值。最优先的是使用程序传递的方式,其次是使用properties文件的方式,最后是使用property子元素的方式。

4.3 settings设置

settings可以深刻影响MyBatis底层的运行,但是在大部分情况下使用默认值就可以运行,所以不需要大量配置,只需要修改常用的规则即可

比如关于缓存的cacheEnabled,关于级联的lazyLoadingEnabledaggressiveLazyLoading,关于自动映射的autoMappingBehaviormapUnderscoreToCamelCase等等

4.4 typeAliases别名

由于类的全限定名很长,所以在大量使用时,一般采用一个简写来代表这个类,这就是别名

在MyBatis的初始化过程中,系统自动初始化了一些别名,例如_int_int[]list等,同时,Configure对象也对一些常用的配置类设置了别名,比如事务方式别名、数据源类型别名、缓存策略别名、语言驱动别名等。

MyBatis也提供了用户自定义别名的规则。我们可以通过TypeAliasRegister类的registerAlias方法注册,也可以采用配置文件或者扫描方式来自定义它。

1
2
3
4
<typeAliases>
<typeAlias alias="role" type="com.neu.edu.pojo.Role"/>
<typeAlias alias="user" type="com.neu.edu.pojo.User">
</typeAliases>

如果有很多类需要定义别名,可以通过扫描包的方式来实现

1
2
3
<typeAliases>
<package name="com.neu.edu.pojo"/>
</typeAliases>

默认情况下,Mybatis会扫描这个包中的类,将其第一个字母变为小写作为其别名,例如Role的别名会变为role。若出现重名的情况,Mybatis允许使用注解@Alias("role2")的方式来进行避免

1
2
3
4
5
package com.neu.edu.pojo
@Alias("Role2")
public Class Role{
...
}

4.5 typeHandler类型转换器

typeHandler的作用是完成jdbcTypejavaType之间的相互转换,其中jdbcType用于定义数据库类型,而javaType用来定义Java类型。

系统提供的typeHandler可以覆盖大部分场景的要求,假如有特殊需求,也可以自己定义特殊的转换规则

4.5.1 系统定义的TypeHandler

MyBatistypeHandler都要实现接口org.apache.ibatis.type.TypeHandler,此接口的定义如下

1
2
3
4
5
6
public interface TypeHandler<T>{
void setParameter(PreparedStatement ps, int i, T parameter, jdbcType jdbcType) throws SQLException;
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
  • 其中T是泛型,专指javaType,比如我们需要String的时候,实现类可以写为implements TypeHandler<String>
  • setParameter方法,是使用typeHandler通过PreparedStatement对象进行设置SQL参数的时候使用的具体方法
  • getResult方法,是从JDBC结果集中获取数据并进行转换,要么使用列名,要么使用下标

MyBatis系统提供的typeHandler都继承了org.apache.ibatis.type.BaseTypeHandler

然后,采用org.apache.ibatis.type.TypeHandlerRegister类对象中的register方法进行注册

4.5.2 自定义的TypeHandler

  1. 首先要自定义一个类,要么实现TypeHandler接口,要么继承BaseTypeHandler

  2. 然后在配置文件中对这个新建的typeHandler进行注册

1
2
3
4
<typeHandlers>
<typeHandler jdbcType="VARCHAR" javaType="string"
handler="com.edu.neu.typeHandler.MyTypeHandler" />
</typeHandlers>
  1. 配置完成后系统就会读取它,当jdbcTypejavaTypeMyTypeHandler对应的时候,就会启动MyTypeHandler

4.5.3 枚举typeHandler

MyBatis对数据库的Blob字段也进行了支持,它提供了一个BlobTypeHandler

在现实中,一次性将大量数据加载到JVM中,会给服务器带来很大压力,所以在更多的时候要考虑使用文件流的形式,这时要将POJO的属性修改为InputStream

4.6 ObjectFactory(对象工厂)

当创建结果集时,MyBatis会使用一个对象工厂来完成创建这个结果集实例。在默认情况下,MyBatis会使用其定义的对象工厂DefaultObjectFactory来完成对应的工作

MyBatis也允许注册自定义的ObjectFactory

  1. 实现ObjectFactory接口或者继承DefaultObjectFactory
  2. 在配置文件中注册
    1
    2
    3
    <objectFactory type="com.edu.neu.MyObjectFactory">
    <property name="prop1" value="value1">
    </objectFactory>

4.7 插件

插件是MyBatis中最强大和灵活的组件,同时也是最复杂、最难使用的组件,它十分危险,会覆盖MyBatis底层对象的核心方法和属性

4.8 运行环境(Environment)

MyBatis中,运行环境主要的作用是配置数据库信息,它可以配置多个数据库,一般而言只需要配置其中的一个就可以

它下面又分为两个可配置的元素:事务管理器(transactionManager)和数据源(dataSource)

4.8.1 transactionManager(事务管理器)

transactionManager提供两个实现类,它需要实现接口`Transaction``

1
2
3
4
5
6
7
public interface Transaction{
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
Integer getTimeout() throws SQLException;
}
  • 它的主要工作就是提交(commit)、回滚(rollback)和关闭(close)
  • MyBatisTransaction提供了两个实现类:JdbcTransactionManagedTransaction
  • JdbcTransaction是以JDBC的方式对数据库的提交和回滚进行操作
  • ManagedTransaction的提交和回滚不用任何操作,而是把事务交给容器处理

在配置文件中,可以通过如下配置,决定使用哪种Transaction方式

1
2
<transactionManager type="JDBC"/>
<transactionManager type="MANAGED"/>

4.8.2 environment(数据源环境)

environment的主要作用是配置数据库

1
2
3
4
5
<environment>
<dataSource type="UNPOOLED">
<dataSource type="POOLED">
<dataSource type="JNDI">
</environment>
4.8.2.1 UNPOOLED

UNPOOLED采用非数据库池的管理方式,每次请求会打开一个新的数据库连接,所以创建会比较慢,在一些对性能没有很高要求的场合可以使用它

UNPOOLED类型的数据源可以配置如下几个属性

  • driver数据库驱动名
  • url连接数据库的URL
  • username用户名
  • passowrd密码
  • defaultTransactionIsolationLevel默认的连接事务隔离级别
4.8.2.2 POOLED

数据源POOLED利用池的概念将JDBCConnection对象组织起来,它开始会有一些空置并且已经连接好的数据库连接,所以请求时,无须再建立和验证,省去去了创建新的连接实例时所必须的初始化和认证时间

4.8.2.3 JNDI

数据源JNDI的实现是为了能在如EJB或应用服务器这类容器中使用

4.9 databaseIdProvider数据库厂商标识

此元素主要是支持多种不同厂商的数据库,来提升可移植性

4.10 引入映射器的方法

  1. 用文件路径引入映射器

    1
    2
    3
    <mappers>
    <mapper resourse="com/learn/ssm/mapper/roleMapper.xml"/>
    </mappers>
  2. 用包名引入映射器

    1
    2
    3
    <mappers>
    <package name="com.learn.ssm.mapper"/>
    </mappers>
  3. 用类注册引入映射器

    1
    2
    3
    4
    <mappers>
    <mapper class="com.learn.ssm.mapper.UserMapper"/>
    <mapper class="com.learn.ssm.mapper.RoleMapper"/>
    </mappers>
  4. userMapper.xml引入映射器

    1
    2
    3
    4
    <mappers>
    <mapper url="file:///var/mappers/com/learn/ssm/mapper/roleMapper.xml"/>
    <mapper url="file:///var/mappers/com/learn/ssm/mapper/userMapper.xml"/>
    </mappers>