MyBatis core configuration

Preface

In fact, the core of MyBatis should be two configuration files, a global configuration file and a mapping file. As long as you understand these two files, you will understand most of the use of MyBatis. This article introduces these two configuration files.

Global configuration file

MyBatis' configuration file contains settings and property information that deeply affects the behavior of MyBatis. The top-level structure of the configuration document is as follows:

  • configuration
  • properties
  • settings
  • typeAliases (type aliases)
  • typeHandlers (type handlers)
  • objectFactory (object factory)
  • plugins
  • environments (environment configuration)
    • environment (environment variable)
      • transactionManager
      • dataSource (data source)
  • databaseIdProvider (database vendor identification)
  • mappers

configuration

Configuration is the root tag of the entire configuration file, which actually corresponds to the most important configuration class Configuration in MyBatis. It runs through every aspect of the MyBatis execution process.

properties

The first level label is properties, which is used to configure parameter information, such as the most common database connection information.

In order to avoid writing the parameters directly in the xml configuration file, we can put these parameters separately in the properties file, introduce them with the properties tag, and then quote them with ${} in the xml configuration file. You can use resource to reference the relative path in the application, or you can use url to specify the absolute path of the local server or network.

<?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 resource="db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

</configuration>

settings

These are extremely important tweaks in MyBatis that will change the runtime behavior of MyBatis.

Setting parameters describe Valid values default value
cacheEnabled Globally turns on or off any cache that has been configured for all mappers in the configuration file. true false
lazyLoadingEnabled Global switch for lazy loading. When enabled, all associated objects are loaded lazily. In a specific association, the switch state of the item can be overridden by setting the fetchType attribute. true false
aggressiveLazyLoading When enabled, any method call will load all properties of the object. Otherwise, each property is loaded on demand (see lazyLoadTriggerMethods). true false
multipleResultSetsEnabled Whether to allow a single statement to return multiple result sets (requires compatible driver). true false
useColumnLabel Use column labels instead of column names. Different drivers will have different performances in this regard. For details, you can refer to the relevant driver documentation or observe the results of the driver used by testing these two different modes. true false
useGeneratedKeys Allowing JDBC to support automatic generation of primary keys requires driver compatibility. If set to true, this setting forces the use of automatically generated primary keys, which will still work despite some incompatible drivers (such as Derby). true false
autoMappingBehavior Specifies how MyBatis should automatically map columns to fields or properties. NONE means to cancel automatic mapping; PARTIAL will only automatically map result sets that do not define nested result set mapping. FULL automatically maps arbitrarily complex result sets (nested or not). NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior Specifies the behavior of discovery auto-mapping that targets unknown columns (or unknown attribute types). NONE: No response WARNING: Output reminder log (the log level of 'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' must be set to WARN) FAILING: Mapping failed (throws SqlSessionException) NONE, WARNING, FAILING NONE
defaultExecutorType Configure the default executor. SIMPLE is an ordinary executor; the REUSE executor will reuse prepared statements; the BATCH executor will reuse statements and perform batch updates. SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout Set the timeout, which determines the number of seconds the driver waits for a response from the database. any positive integer Not Set (null)
defaultFetchSize Set a hint value for the driver's result set fetch size (fetchSize). This parameter can only be overridden in query settings. any positive integer Not Set (null)
safeRowBoundsEnabled Allows the use of paging (RowBounds) in nested statements. Set to false if use is allowed. true false
safeResultHandlerEnabled Allow pagination (ResultHandler) in nested statements. Set to false if use is allowed. true false
mapUnderscoreToCamelCase Whether to enable automatic camel case mapping, that is, a similar mapping from the classic database column name A_COLUMN to the classic Java attribute name aColumn. true| false False
localCacheScope MyBatis uses the local cache mechanism (Local Cache) to prevent circular references and speed up repeated nested queries. The default value is SESSION, in which case all queries executed in a session are cached. If the setting value is STATEMENT, the local session is only used for statement execution, and different calls to the same SqlSession will not share data. SESSION| STATEMENT SESSION
jdbcTypeForNull When no specific JDBC type is provided for the parameter, the JDBC type is specified for the null value. Some drivers need to specify the JDBC type of the column. In most cases, just use the general type, such as NULL, VARCHAR or OTHER. JdbcType constants. Most are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods Specify which object method triggers a lazy load. Comma separated list of methods. equals,clone,hashCode,toString
defaultScriptingLanguage Specifies the default language for dynamic SQL generation. A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler Specifies the default TypeHandler used by Enum. (Since 3.4.5) A type alias or fully qualified class name. org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls Specifies whether to call the map object's setter (put for map object) method when the value in the result set is null. This is useful when there is a Map.keySet() dependency or null value initialization. Note that basic types (int, boolean, etc.) cannot be set to null. true| false false
returnInstanceForEmptyRow When all columns of the returned row are empty, MyBatis returns null by default. When this setting is turned on, MyBatis will return an empty instance. Note that it also works with nested result sets (ie collectioin and association). (Since 3.4.2) true| false false
logPrefix Specify the prefix that MyBatis adds to the log name. any string Not set
logImpl Specify the specific implementation of the log used by MyBatis. If not specified, it will be automatically searched. SLF4J LOG4J| LOG4J2 | JDK_LOGGING | COMMONS_LOGGING\
proxyFactory Specify the proxy tool used by Mybatis to create objects with lazy loading capabilities. CGLIB\ JAVASSIST
vfsImpl Specify VFS implementation Fully qualified class names of custom VFS implementations, separated by commas. Not set
useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始) true| false true
configurationFactory 指定一个提供Configuration实例的类。 这个被返回的Configuration实例用来加载被反序列化对象的懒加载属性值。 这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始) 类型别名或者全类名. Not set

案例

    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />

        <!-- 控制全局缓存(二级缓存),默认 true-->
        <setting name="cacheEnabled" value="false"/>

        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="true"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--
                <setting name="localCacheScope" value="STATEMENT"/>
        -->
        <setting name="localCacheScope" value="SESSION"/>
    </settings>

typeAliases

TypeAlias是类型的别名,主要用来简化类名全路径的拼写。比如参数类型和返回值类型都可能会用到我们的Bean,如果每个地方都配置全路径的话,那么内容就比较多,还可能会写错。

可以为Bean创建别名,既可以指定单个类,也可以指定一个package,自动转换。

    <typeAliases>
        <typeAlias alias="user" type="com.domain.User" />
    </typeAliases>

MyBatis里面有很多系统预先定义好的类型别名,在TypeAliasRegistry中。所以可以用string代替java.lang.String。

  public TypeAliasRegistry() {
    
    
    registerAlias("string", String.class);

    registerAlias("byte", Byte.class);
    registerAlias("long", Long.class);
    registerAlias("short", Short.class);
    registerAlias("int", Integer.class);
    registerAlias("integer", Integer.class);
    registerAlias("double", Double.class);
    registerAlias("float", Float.class);
    registerAlias("boolean", Boolean.class);

    registerAlias("byte[]", Byte[].class);
    registerAlias("long[]", Long[].class);
    registerAlias("short[]", Short[].class);
    registerAlias("int[]", Integer[].class);
    registerAlias("integer[]", Integer[].class);
    registerAlias("double[]", Double[].class);
    registerAlias("float[]", Float[].class);
    registerAlias("boolean[]", Boolean[].class);

    registerAlias("_byte", byte.class);
    registerAlias("_long", long.class);
    registerAlias("_short", short.class);
    registerAlias("_int", int.class);
    registerAlias("_integer", int.class);
    registerAlias("_double", double.class);
    registerAlias("_float", float.class);
    registerAlias("_boolean", boolean.class);

    registerAlias("_byte[]", byte[].class);
    registerAlias("_long[]", long[].class);
    registerAlias("_short[]", short[].class);
    registerAlias("_int[]", int[].class);
    registerAlias("_integer[]", int[].class);
    registerAlias("_double[]", double[].class);
    registerAlias("_float[]", float[].class);
    registerAlias("_boolean[]", boolean[].class);

    registerAlias("date", Date.class);
    registerAlias("decimal", BigDecimal.class);
    registerAlias("bigdecimal", BigDecimal.class);
    registerAlias("biginteger", BigInteger.class);
    registerAlias("object", Object.class);

    registerAlias("date[]", Date[].class);
    registerAlias("decimal[]", BigDecimal[].class);
    registerAlias("bigdecimal[]", BigDecimal[].class);
    registerAlias("biginteger[]", BigInteger[].class);
    registerAlias("object[]", Object[].class);

    registerAlias("map", Map.class);
    registerAlias("hashmap", HashMap.class);
    registerAlias("list", List.class);
    registerAlias("arraylist", ArrayList.class);
    registerAlias("collection", Collection.class);
    registerAlias("iterator", Iterator.class);

    registerAlias("ResultSet", ResultSet.class);
  }

TypeHandler

由于Java类型和数据库的JDBC类型不是一一对应的(比如String与varchar、char、text),所以把Java对象转换为数据库的值,和把数据库的值转换成Java对象,需要经过一定的转换,这两个方向的转换就要用到TypeHandler。

我们可以自定义一个TypeHandler来帮助我们简单的处理数据,比如查询的结果的字段如果是一个字符串,且值为"zhangsan"就修饰下这个信息


/**
 * 自定义的类型处理器
 *    处理的字段如果是 String类型的话就 且 内容是 zhangsan 拼接个信息
 */

public class MyTypeHandler  extends BaseTypeHandler<String> {
    
    
    /**
     * 插入数据的时候回调的方法
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    
    
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
    
    
        String name = rs.getString(columnName);
        if("zhangsan".equals(name)){
    
    
            return name+"666";
        }
        return name;
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    
    
        String name = rs.getString(columnIndex);
        if("zhangsan".equals(name)){
    
    
            return name+"666";
        }
        return name;
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    
    
        String name = cs.getString(columnIndex);
        if("zhangsan".equals(name)){
    
    
            return name+"666";
        }
        return name;
    }
}

同时将我们的处理器在全局配置文件中注册下

<typeHandlers>
    <typeHandler handler="com.type.MyTypeHandler"></typeHandler>
</typeHandlers>

然后我们在映射文件中配置对应的处理器

image.png

objectFactory

当我们把数据库返回的结果集转换为实体类的时候,需要创建对象的实例,由于我们不知道需要处理的类型是什么,有哪些属性,所以不能用new的方式去创建,只能通过反射来创建。

在MyBatis里面,它提供了一个工厂类的接口,叫做ObjectFactory,专门用来创建对象的实例(MyBatis封装之后,简化了对象的创建),里面定义了4个方法。

public interface ObjectFactory {
    
    

  default void setProperties(Properties properties) {
    
    
    // NOP
  }
  <T> T create(Class<T> type);
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
  <T> boolean isCollection(Class<T> type);

}
方法 作用
void setProperties(Properties properties); 设置参数时调用
T create(Class type); 创建对象(调用无参构造函数)
T create(Class type, List<Class<?>> constructorArgTypes, List constructorArgs); 创建对象(调用带参数构造函数)
boolean isCollection(Class type) 判断是否集合

ObjectFactory有一个默认的实现类DefaultObjectFactory。创建对象的方法最终都调用了instantiateClass(),这里面能看到反射的代码。

默认情况下,所有的对象都是由DefaultObjectFactory创建。

/**
 *
 * 自定义ObjectFactory,通过反射的方式实例化对象
 * 一种是无参构造函数,一种是有参构造函数——第一个方法调用了第二个方法
 */
public class MyObjectFactory extends DefaultObjectFactory {
    
    

    @Override
    public Object create(Class type) {
    
    
        System.out.println("创建对象方法:" + type);
        if (type.equals(User.class)) {
    
    
            User blog = (User) super.create(type);
            blog.setUserName("object factory");
            blog.setId(1111);
            blog.setRealName("张三");
            return blog;
        }
        Object result = super.create(type);
        return result;
    }

}

plugins

插件是MyBatis的一个很强大的机制。跟很多其他的框架一样,MyBatis预留了插件的接口,让MyBatis更容易扩展。详细内容

environments

environments标签用来管理数据库的环境,比如我们可以有开发环境、测试环境、生产环境的数据库。可以在不同的环境中使用不同的数据库地址或者类型。

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

environment

一个environment标签就是一个数据源,代表一个数据库。这里面有两个关键的标签,一个是事务管理器,一个是数据源。

transactionManager

如果配置的是JDBC,则会使用Connection对象的commit()、rollback()、close()管理事务。

如果配置成MANAGED,会把事务交给容器来管理,比如JBOSS,Weblogic。因为我们跑的是本地程序,如果配置成MANAGE不会有任何事务。

如果是Spring + MyBatis,则没有必要配置,因为会直接在applicationContext.xml里面配置数据源和事务,覆盖MyBatis的配置。

dataSource

数据源,顾名思义,就是数据的来源,一个数据源就对应一个数据库。在Java里面,它是对数据库连接的一个抽

一般的数据源都会包括连接池管理的功能,所以很多时候也把DataSource直接 称为连接池,准确的说法应该是:带连接池功能的数据源。

mappers

<mappers>标签配置的是映射器,也就是Mapper.xml的路径。这里配置的目的是让MyBatis在启动的时候去扫描这些映射器,创建映射关系。

有四种指定Mapper文件的方式:

  1. 使用相对于类路径的资源引用(resource)

     <mappers>
         <mapper resource="UserMapper.xml"/>
     </mappers>
    
  2. 使用完全限定资源定位符(绝对路径)(URL)

     <mappers>
         <mapper resource="file:///app/sale/mappers/UserMapper.xml"/>
     </mappers>
    
  3. 使用映射器接口实现类的完全限定类名

    <mappers>
       <mapper class="com.mapper.UserMapper"/>
    </mappers>
    
  4. 将包内的映射器接口实现全部注册为映射器(最常用)

    <mappers>
       <mapper class="com.mapper"/>
    </mappers>
    

映射文件

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,会发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache – 该命名空间的缓存配置。
  • cache-ref – 引用其它命名空间的缓存配置。
  • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
  • sql – 可被其它语句引用的可重用语句块。
  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。

resultMap

是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

<resultMap id="BaseResultMap" type="Employee">
   <id column="emp_id" jdbcType="INTEGER" property="empId"/>
   <result column="emp_name" jdbcType="VARCHAR" property="empName"/>
   <result column="gender" jdbcType="CHAR" property="gender"/>
   <result column="email" jdbcType="VARCHAR" property="email"/>
   <result column="d_id" jdbcType="INTEGER" property="dId"/>
</resultMap>

sql

<sql id="Base_Column_List">
emp_id, emp_name, gender, email, d_id
</sql>

增删改查标签

针对常用的增删改查操作提供的有对应的标签来处理

<insert> – 映射插入语句

<update> – 映射更新语句

<delete> – 映射删除语句

<select
 id="selectPerson"
 parameterType="int"
 parameterMap="deprecated"
 resultType="hashmap"
 resultMap="personResultMap"
 flushCache="false"
 useCache="true"
 timeout="10"
 fetchSize="256"
 statementType="PREPARED"
 resultSetType="FORWARD_ONLY">
属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
resultType 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultOrdered 这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false
resultSets 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。

Guess you like

Origin blog.csdn.net/qq_28314431/article/details/133086274