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>

 

配置的优先级

  1. 在proerties元素体内指定的属性首先被读取
  2. 根据properties元素中的resource属性读取类路径下属性文件,或者根据url属性指定的路径读取属性文件,并覆盖已读取的同名属性
  3. 读取作为方法参数传递的属性,并覆盖已读取的同名属性

建议:不要使用混合的方式,这样会使得管理混乱,首选的方式是使用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>

 

posted @ 2020-11-12 13:44  半雨微凉  阅读(523)  评论(0)    收藏  举报