MyBatis配置总结

Posted nm666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis配置总结相关的知识,希望对你有一定的参考价值。

参考:《JavaEE 互联网轻量级框架整合开发》-第 4 章

技术图片

一、配置概述

<configuration><!--配置-->
    <properties></properties><!--属性-->
    <settings></settings><!--设置-->
    <typeAliases></typeAliases><!--类型命名-->
    <typeHandlers></typeHandlers><!--类型处理器-->
    <objectFactory></objectFactory><!--对象工厂-->
    <plugins></plugins><!--插件-->
    <environments><!--配置环境-->
        <environment><!--环境变量-->
            <transactionManager></transactionManager><!--事务管理器-->
            <dataSource></dataSource><!--数据源-->
        </environment>
    </environments>
    <databaseIdProvider></databaseIdProvider><!--数据库厂商标识-->
    <mappers></mappers><!--映射器-->
</configuration>

注意:MyBatis配置项的顺序不能颠倒,不然启动阶段会发生异常,导致程序无法运行。

二、properties属性

properties可以给系统配置一些运行参数,可以放在xml、properties文件中,而不是放在Java代码中,便于参数的修改维护。3种使用properties的方式:

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

1.property子元素

如下,在property子元素中定义:

<properties>
    ···
    <property name="database.username" value="root"></property>
    <property name="database.password" value="root"></property>
</properties>

使用如下:

<dataSource>
    ···
    <property name="username" value="$database.username"></property>
    <property name="username" value="$database.password"></property>
</dataSource>

2.使用properties文件

跟xml方式同理,只不过我们的配置写在properties文件中,然后通过<properties>的属性resource来引入,同样可以以$xxx的方式引用,如下所示:

①jdbc.properties

database.driver=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/demo
database.username=root
database.password=123456

②引入

<properties resource="jabc.properties"></properties>

3.使用程序传递参数

适用于数据库用户密码加密的形式。

在生产环境环境中,一般会把数据库的用户名和密码生成密文配置到properties中。我们需要从配置文件上读取到加密过的用户名和密码,然后通过解密程序(工具类)进行解密,重置到properties属性中,然后正常连接数据库。演示代码如下:

String resource = "mybatis-config.xml"
InputStream inputStream;
InputStream in = Resources.getResourceAsStream("jdbc.properties");
Properties props = new Properties();
props.load(in);//加载从xml文件读取到的properties配置
String username = props.getProperty("database.username");
String password = props.getProperty("database.password");
//解密用户名和密码并在属性中重置
props.put("database.username",CodeUtis.decode(username));
props.put("database.password",CodeUtis.decode(password));
inputStream = Resources.getResourceAsStream(resource);
//使用程序传递的方式覆盖原有的properties属性参数
SqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream,props);

三、settings 设置

mybatis最复杂的配置,影响mybatis的底层运行。一般默认即可,大部分情况下不需要配置,只需要修改常用规则即可,如自动映射、驼峰命名映射、联级规则、是否启动缓存、执行器类型等。

设置参数 描述 有效值 默认值
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 true | false false
aggressiveLazyLoading 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 true | false 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
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数。 Any positive integer Not Set (null)
defaultFetchSize Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. Any positive integer Not Set (null)
safeRowBoundsEnabled 允许在嵌套语句中使用分页(RowBounds)。 true | false False
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true | false False
localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 SESSION | STATEMENT SESSION
jdbcTypeForNull 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods 指定哪个对象的方法触发一次延迟加载。 A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage 指定动态 SQL 生成的默认语言。 A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 true | false false
logPrefix 指定 MyBatis 增加到日志名称的前缀。 Any String Not set
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
proxyFactory 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 or above)

四、typeAliases别名

别名分为两类:①系统别名、②自定义别名;

注意:mybatis中别名不区分大小写

1.系统定义别名

基本数据类型都,并且支持数组,如int的别名_int;以及他们的包装类,Long的别名long。另外,系统还定义了集合类型的别名,但是不支持相应类型的数组形式。

别名 Java类型 是否支持数组
_byte byte y
_long long y
_short short y
_int int y
_integer int y
_double double y
_float float y
_boolean boolean y
string String y
byte Byte y
long Long y
short Short y
int Integer y
integer Integer y
double Double y
float Float y
boolean Boolean y
date Date y
decimal BigDecimal y
bigdecimal BigDecimal y
object Object y
map Map n
hashmap HashMap n
list List n
arraylist ArrayList n
collection Collection n
iterator Iterator n
ResultSet ResultSet n

有时候需要用代码来实现注册别名:

public TypeAliasRegistry()
    registerAlias("string",String.class);
    registerAlias("JDBC",JdbcTransactionFactory.class);
    ···
    //使用系统类型,不要重复命名;包含类别如下:
    /*
    1.事务方式别名
    2.数据源类型别名
    3.缓存策略别名
    4.数据库标识别名
    5.语言驱动类别名
    6.日志类别名
    7.动态代理别名
    */

2.自定义别名

①直接配置:

<typeAliases>
    <typeAlias alias="user" type="com.example.mybatis.domain.User"></typeAlias>
    <typeAlias alias="role" type="com.example.mybatis.domain.Role"></typeAlias>
</typeAliases>

②包扫描的方式,会自动将包下的类名首字母转小写作为类名,如FileManagement --> fileMangement,包扫描配置如下:

<typeAliases>
    <package name="com.example.file.domain"></package>
</typeAliases>

直接配置,还配置包扫描或者不同包有相同类名,怎么办?

可以再类名上加注解@Alias("user")来区分,这样别名就是我们所注释的别名了。

五、typeHandler类型转换器

在JDBC中,需要在PreparedStatement对象中设置那些已经预编译过的SQL语句的参数。执行SQL后,会通过ResultSet对象获取到数据库的数据,而这些是MyBatis根据数据的类型通过typeHandler来实现。

  • jdbcType 定义数据库字段类型
  • javaType定义Java属性类型

而typeHandler是对两者进行转换的,一般不需要我们去配置typeHandler、jdbcType、javaType。因为MyBatis会自动探测并使用相应类型的typeHandler。

技术图片

  • 系统定义typeHandler
  • 自定义typeHandler

1.系统定义typeHandler

技术图片

  • MyBatis所有的typeHandler都要实现org.apache.ibatis.type.TypeHandler接口
  • setParameter方法,是使用typeHandler通过PreparedStatement对象进行设置SQL参数的时候使用的具体方法,i是参数在SQL的下标,parameter是参数,jdbcType是数据库类型。
  • 3个getResult的方法由来从JDBC结果集中获取数据进行转换;列名(columnName)、下标(columnIndex);最后一个是存储过程专用的。
  • BaseTypeHandler是个抽象类,需要子类继承4个抽象方法,而它本事实现了TypeHandler接口的4个方法。
  • getResult是通过getNullabelResult方法获取的,如果为空就返回null
  • TypeHandlerRegistry类对象的regist方法区注册这些TypeHandler
  public TypeHandlerRegistry() 
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());
      ...
  

2.自定义typeHandler

由系统定义的类型转换器可知,我们自定义typeHandler需要实现TypeHandler接口或者继承BaseTypeHandler类。我们可以仿造一个StringTypeHandler:

public class MyTypeHandler implements TypeHandler<String>
    ...
    @Override
    public xxx
    ...

那么接下来配置typeHandler(注册)

<typeHandlers>
    <typeHandler jdbcType="VARCHAR" javaType="string" handler="com.example.mybatis.typehandler.MyTypeHandler"></typeHandler>
</typeHandlers>

配置完成后,系统就会读取,当jdbcType和javaType能与MyTypeHandler对应起来的时候,就启动MyTypeHandler。也可以显示启用typeHandler:

(1)

<resultMap id="roleMapper" type="user">
    <result property="userName" column="user_name" jdbcType="VARCHAR" javaType="string"
</resultMap>
    
<select id="selectUser" parameterType="string" resultMap="roleMapper">
    select * from user where user_name like concat('%', #userName,jdbcType=VARCHAR,javaType=string,'%')    
</select>

(2)

<resultMap id="roleMapper" type="user">
    <result property="userName" column="user_name" typeHandler="com.example.mybatis.typehandler.MyTypeHandler"
</resultMap>
    
<select id="selectUser" parameterType="string" resultMap="roleMapper">
    select * from user where user_name like concat('%', #userName,typeHandler=com.example.mybatis.typehandler.MyTypeHandler,'%')    
</select>

注意:要么指定与自定义typeHandler一致的jdbcType和javaType【如(1)】,要么直接typeHandler指定具体的实现类【如(2)】。

有时候枚举类型多,或者我们自定义的typeHandler很多的时候,采用配置也会很麻烦,我们可以采用包扫描的方式:

<typeHandlertype>
    <package name="com.example.mybatis.typehandler" />
</typeHandlertype>

但是这样就没法指定jdbcType和javaType,不过我们可以用注解来处理,把MyTypeHandler的声明修改一下:

@MappedTypes(String.class)
@MappedjdbcTypes(jdbcType.VARCHAR)
public class MyTypeHandler implements TypeHandler<String>
    ...

3.枚举typeHandler

mybatis已经帮我们定义好了两个类作为枚举类型的支持:

  • EnumOrdinalTypeHandler
  • EnumTypeHandler

我们先定义一个枚举类型,来查看查看两者区别:

/**
 * @author BastetCat
 * @data 2019/7/23 23:31
 */

public enum SexEnum 
    MALE(1,"男"),
    FEMALE(0,"女");

    private int id;
    private String name;

    SexEnum(int id, String name) 
        this.id = id;
        this.name = name;
    
    public SexEnum getSexById(int id)
        for (SexEnum sex:SexEnum.values())
            if(sex.getId() == id)
                return sex;
            
        
        return null;
    

    public int getId() 
        return id;
    

    public String getName() 
        return name;
    

(1)EnumOrdinalTypeHandler是MyBatis根据枚举数组下标索引的方式进行匹配的,也是枚举的默认转换类,使用:

<resultMap id="userMapper" type="user">
    <result property="sex" column="sex" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
</resultMap>

(2)EnumTypeHandler会把名称转换成对应的枚举,使用:

<resultMap id="userMapper" type="user">
    <result property="sex" column="sex" typeHandler="org.apache.ibatis.type.EnumTypeHandler"
</resultMap>

对于上(1)来说数据库存放的是 1或0,而(2)中存放的MALE或FEMALE

自定义枚举

@MappedTypes(SexEnum.class)
@MappedjdbcTypes(jdbcType.INTEGER)
public class MyTypeHandler implements TypeHandler<SexEnum>
    ...

4.文件操作BlobTypeHandler

更多时候文件流的方式:BlobInputStreamTypeHandler

但是性能不佳,我们都会有单独的文件服务器。

六、ObjectFactory(对象工厂)

用来创建结果集

自定义需要实现org.apache.ibatis.reflection.factory.ObjectFactory接口,然后配置:

<objectFactory type="xxx(ObjectFactory的实现类)">
    <property name="xx" value="xx"></property>
</objectFactory>

七、plugins(插件)

八、environments(运行环境)

  • transactionManager(事务管理器)
  • dataSource(数据源)
<environment default="development">
    <environment id="development">
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <property name="dirver" value="$database.driver"></property>
            <property name="url" value="$database.url"></property>
            <property name="username" value="$database.username"></property>
            <property name="password" value="$database.password"></property>
        </dataSource>
    </environment>
</environment>

1.transactionManager

public interface Transaction
    Connection getConnection() throws SQLException;
    void commit() throws SQLException;//提交
    void rollback() throws SQLException;//回滚
    void close() throws SQLException;//关闭
    Integer getTimeout() throws SQLException;

它有两个实现类,分别是JdbcTransaction、ManagedTransaction,可以把事务管理器配置成为一下两种方式:

<!--使用JdbcTransactionFactory生成jdbcTransaction对象,以JDBC的方式对数据进行提交和回滚操作-->
<transactionManager type="JDBC" />
<!--ManagedTransactionFactory生成ManagedTransaction 不进行任何操作,把事务交给容器处理;closeConnection="false"来阻止默认关闭行为,从而让容器处理-->
<transactionManager type="MANAGED" closeConnection="false" />

自定义的话就是:

<transactionManager type="com.example.mybatis.transaction.MyTransaction" />

2.environment数据源环境

environment 的主要作用是配置数据库,在 MyBatis 中, 数据库通过 PooledDataSourceFactory 、UnpooledDataSourceFactory 和 JndiDataSourceF actory 三个工厂类来提供,前两着对应产生 PooledDataSource 、UnpooledDataSource 类对象,而 JndiDataSourceFactory 则会根据则DI 信息拿到外部容器实现的数据库连接对象。无论如何这 个工厂类,最后生成的产品都会是一个实现了 DataSource 接口的数据库连接对象。

<dataSource type="UNPOOLED">
<dataSource type= "POOLED">
<dataSource type= "JNDI" >

UNPOOLED

UNPOOLED 采用非数据库池的管理方式,每次请求都会打开 个新的数据库连接,所以创建会比较慢。在 些对性能没有很高要求的场合可以使用它。对有些数据库而言,使用连接池井不重要,那么它也是一个比较理想的选择。 POOLED 类型的数据源可以配置以下几种属性:

  • driver 数据库驱动名,比如 MySQL的 com.mysql be.Driver
  • url 连接数据库的 URL
  • usemame 用户名。
  • password 密码。
  • defaultTransactionlsolationLevel 默认的连接事务隔离级别

传递属性给数据库驱动也是 个可选项,注意属性的前缀为“ driver. ”,例如driver.e ncoding=UTF8 。它会通过 DriverManager.getConnection(url,driverProperties 方法传递值为 UTF8 的encoding 属性给数据库驱动。

POOLED
数据源 POOLED 利用“池”的概念将 JDBC Connection 对象组织起来 它开始会有一些空置,并且已经连接好的数据库连接,所以请求时 无须再建立和验证,省去了创建新的连接实例时所必需的初始化和认证时间。它还控制最大连接数,避免过多的连接导致系统瓶颈。

除了 UNPOOLED 下的属性外,会有更多属性用来配置 POOLED 的数据源:

  • poolMax mumActiveConnections 是在任意时间都存在的活动( 也就是正在使用)连接数量,默认值为 10
  • poolMax murnldleConnections 是任意时间可能存在的空闲连接数。
  • poolMaximumCheckoutTime 在被强制返回之前,池中连接被检出( checked out )的时间,默认值为20000毫秒( 20 秒)。
  • poolTimeToWait 个底层设置,如果获取连接花费相当长的时间,它会给连接池打印状态日志 并重新尝试获取一个连接(避免在误配置的情况下 直失败)默认值为 20 000 毫秒(即 20 )。
  • poolPingQuery 为发送到数据库的侦 查询,用来检验连接是否 在正常工作秩序中,并准备接受请求。默认是“NO PING QUERY SET ”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。

  • poolPingEnabled 为是否启用侦测查询。若开启,也必须使用一个可执行的 SQL语句设置 poolPingQuery 属性(最好是 个非常快的 SQL) ,默认值为 false
  • poolPingConnectionsNotUsedFor 为配置 poo!PingQuery 使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值为 0(即所有连接每一时刻都被侦测一一仅 poolPingEnabled为true 适用)。

JNDI

数据源 JNDI的 实现是为了能在如 EJB 或应用服务器这类容器中使用 容器可以集中或在外部配置数据源,然后放置一 JNDI 上下文的引用 。这种数据源配置只需要两个属性:

  • initial_ context 用来在 Initial Context 寻找上下文(即, initialContext.lookup(initial_context )initial_context 是个可选属性,如果忽略 那么 datasource 属性将会直接从InitialContext 寻找。
  • data_source 是引用数据源实例位置上下文的路径。当提供 initial_context配 置时,data_source 会在其返回的上下文中进行查找 当没有提供 initial_context 时,data_source 直接在 InitialContext 中查找

九、databaseIdProvider(数据库厂商标识)

databaseldProvider 元素主要是支持多种不同厂 的数据 。

<databaseidProvider type="DBVENDOR" >
    <!--connection.getMetaData().getDatabaseProductName()获取数据库别名-->
    <property name= "Oracle" value= "oracle" />
    <property name= "MySQL" value = "mysql"/>
    <property name= "DB2" value= "db2"/>
</databaseidProvider> 

改造映射器SQL,标识一条SQL应用于那个数据库中:

<select id= "getRole" parameterType="long" resultType= "role" databaseId="oracle" >
    select id, role_name as roleName, note from t_role where id = # id 
</select> 
<select id="getRole" parameterType="long" resultType="role" databaseId="mysql" >
    select id,role_name as roleName , note from t_role where 1=1 and id = #id 
</select> 

十、引入映射器的方法

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

<mappers> 
    <mapper resource="com/learn/ssm/chapter4/mapper/roleMapper.xml"/>
</mappers> 

2.用包名引入映射器

<mappers> 
    <package name="com.learn.ssm.chapter4.mapper"/> 
</mappers> 

3.用类注册引入映射器

<mappers> 
    <mapper class="com.learn.ssm.chapter4.mapper.UserMapper"/>
    <mapper class="com.learn.ssm.chapter4.mapper.RoleMapper"/>
</mapper> 

4.用userMapper.xml引入映射器

<mappers> 
    <mapper url="file:///var/mappers/com/learn/ssm/chapter4/mapper/roleMapper.xml" />
    <mapper url="file:///var/mappers/com/learn/ssm/chapter4/mapper/RoleMapper.xml" />
</mappers > 

以上是关于MyBatis配置总结的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis学习总结——优化MyBatis配置文件中的配置

Mybatis框架学习总结-优化Mybatis配置文件中的配置

MyBatis学习总结——MyBatis核心配置文件与输入输出映射

MyBatis学习总结_03_优化MyBatis配置文件中的配置

Mybatis总结:mybatis的配置详解

MyBatis学习总结——优化MyBatis配置文件中的配置