Mybatis配置文件的详解

367 阅读15分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

一、日志的配置

在实际项目中我们会配置一些日志来记录程序关键运行节点的相关信息,最重要的是需要记录程序运行过程中的错误信息,以便于我们来解决问题。

目前市面上日志框架有JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

其中应用相对较多的为logback、log4j、slf4j.

其中slf4j为日志门面,相当于与一个“日志店铺”,然后可以对一些日志进行对接管理。

目前应用比较多的为slf4j+logback+log4j,下面来演示集成slf4j+logback。

日志门面: SLF4J; 官方文档:www.slf4j.org/

日志实现:Logback; 中文文档:www.logback.cn/

1-1、导入pom

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>

1-2、执行测试方法,可以看到日志输出

image.png 我们可以看到虽然只是引入了logback的jar包,但是logbakc就开始工作了,那具体是怎么工作的呢?

1-3、logback 的初始化步骤:

1.logback 会在类路径下寻找名为 logback-test.xml 的文件。

2.如果没有找到,logback 会继续寻找名为 logback.groovy 的文件。

3.如果没有找到,logback 会继续寻找名为 logback.xml 的文件。

4.如果没有找到,将会通过 JDK 提供的 ServiceLoader 工具在类路径下寻找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator,该文件的内容为实现了 Configurator 接口的实现类的全限定类名。

5.如果以上都没有成功,logback 会通过 BasicConfigurator 为自己进行配置,并且日志将会全部在控制台打印出来。

最后一步的目的是为了保证在所有的配置文件都没有被找到的情况下,提供一个默认的(但是是非常基础的)配置。

如果你使用的是 maven,你可以在 src/test/resources 下新建 logback-test.xml。maven 会确保它不会被生成。所以你可以在测试环境中给配置文件命名为 logback-test.xml,在生产环境中命名为 logback.xml

1-4、日志级别

这条规则是 logbakc 的核心。各级别的排序为:TRACE < DEBUG < INFO < WARN < ERROR

如果设置日志级别为DEBUG,那么大于它的信息都会输出。

1-4-1、日志级别测试

目前在没有配置日志级别的情况下,more是DEBUG级别,那么我们把每个级别都进行输出看一下,除了TRACE级别,其他级别都成功输出。 image.png

1-4-2、给某个包或者类设置单独的日志级别

假如我们给系统全局设置了error日志级别,但是又想看到程序执行的相关sql,就需要单独进行配置,一般我们把查询都写在mapper下,那么我们设置mapper包就可以输出所有执行的语句了,如下:

image.png

1-4-2-1、测试

image.png 可以看到只输出了debug日志级别

1-5、我们自己使用logback

1-5-1、创建logback.xml文件

image.png

1-5-2、测试

我们把debug级别改为error,看下输出结果

image.png 通过上图可以看到,只有输出级别为error的才可以正常输出。

1-6、自定义日志输出

1-6-1、注入日志

初始化logger,这个地方一定要引用slf4j,要不后面换日志包,就比较麻烦了 image.png

通过以下代码就可以将日志注入了

image.png

1-6-2、输出日志信息

image.png 将info改为error

image.png 可以看到这样就可以正常输出日志了。

二、mybatis全局配置文件详解

在mybatis的项目中,我们发现了有一个mybatis­config.xml的配置文件,这个配置文件是mybatis的全局配置文件,用来进行相关的全局配置,在任何操作下都生效的配置。

官网中告诉我们配置文档的结构如下: image.png

2-1、环境配置

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。

2-1-1、数据库环境配置

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

注意一些关键点:

  • 默认使用的环境 ID(比如:default="development")。
  • 每个 environment 元素定义的环境 ID(比如:id="development")。
  • 事务管理器的配置(比如:type="JDBC")。
  • 数据源的配置(比如:type="POOLED")。

默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

如下:我这边设置的数据库连接信息

<environments default="development">
    <!--environment 配置数据库环境 id:指定当前数据库环境的唯一标识,会被父节点default所设置-->
    <environment id="development">
        <!--transactionManager 设置事务管理器,type:指定事务管理器类型
            type= JDBC  使用JDBC的事务管理器
            type=MANAGED 不使用事务
         -->
        <transactionManager type="JDBC"/>
        <!-- dataSource 配置数据源 type:指定数据库连接池
            type=  POOLED  指定mybatis的连接池
            type= UNPOOLED 不使用连接池,每次使用都打开和关闭
            type= JNDI JNDK连接池 在容器中使用的连接池如tomcat
         -->
        <dataSource type="POOLED">
            <!--配置数据库相关信息 以及连接池信息-->
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </dataSource>
    </environment>
</environments>

2-1-2、多数据源配置

一套系统发布到线上我们使用线上的数据源,但是如果在开发环境就需要使用测试的数据库,因此我们需要配置多个数据源,如下:

复制一份environment,并将ID改为test 作为测试数据库。

image.png

然后将数据源改为test,当前环境即为测试环境了 image.png

2-2、映射器

既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

以上四种一般情况下,我们采用使用最后一种,这样配置一条就可以将全部mapper进行注册了。

2-3、settings设置

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。truefalsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。truefalsefalse
aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。truefalsefalse (在 3.4.1 及之前的版本中默认为 true)
multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。truefalsetrue
useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。truefalsetrue
useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。truefalseFalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。- NONE: 不做任何反应 WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN
FAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLYSCROLL_SENSITIVESCROLL_INSENSITIVEDEFAULT(等同于未设置)未设置 (null)
safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。truefalseFalse
safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。truefalseTrue
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。truefalseFalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSIONSTATEMENTSESSION
jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。truefalsefalse
returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)truefalsefalse
logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4JLOG4J(deprecated since 3.5.9)LOG4J2JDK_LOGGINGCOMMONS_LOGGINGSTDOUT_LOGGINGNO_LOGGING未设置
proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIBJAVASSISTJAVASSIST (MyBatis 3.3 以上)
vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)truefalsetrue
configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置
shrinkWhitespacesInSql从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5)truefalsefalse
defaultSqlProviderTypeSpecifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.A type alias or fully qualified class nameNot set
nullableOnForEachSpecifies the default value of 'nullable' attribute on 'foreach' tag. (Since 3.5.9)truefalsefalse

一个配置完整的 settings 元素的示例如下:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

以上部分一般不需要进行设置。使用默认即可。

2-4、properties

有些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。比如我们数据库的配置信息,就可以进行这样处理。

2-4-1、首先创建一个db.properties

创建一个db.properties可以保存数据库驱动相关信息,如下:

image.png

2-4-2、使用properties加载文件

<!--配置外部属性资源文件  通过${}进行引用-->
<properties resource="db.properties"/>

如下可以看到通过properties这样引入外部的的属性文件,然后通过使用${}就可以成功使用属性了。 image.png

2-4-3、同样也可以在properties中指定key值

image.png

2-5、 类型别名(typeAliases)

2-5-1、通过tyeAlias 设置别名

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<typeAliases>
  <typeAlias alias="Emp" type="com.jony.pojo.Emp"/>
</typeAliases>

当这样配置时,Emp 可以用在任何使用 com.jony.pojo.Emp 的地方。

2-5-2、通过指定包名设置别名

可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="com.jony.pojo"/>
</typeAliases>

每一个在包 com.jony.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的非限定类名来作为它的别名。 比如 com.jony.pojo.Emp 的别名为 emp(忽略大小写)

2-5-3、通过注解设置别名

若有注解,则别名为其注解值。见下面的例子:

@Alias("emp")
public class Emp {
    ...
}

2-5-4、常见java类型内建的类型别名

以下为常见的java类型内建的类型别名,它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

这样我们在通过mybatis查询的时候就可以不用写完整限定名,直接下别名即可,如下

image.png

2-6、数据库厂商的设置

MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider即可。

2-6-1、如何获得数据库厂商的ID

image.png 通过上图可以看到mysql的厂商ID即为 MySQL

2-6-2、在mybatis全局配置文件中设置数据库厂商

databaseIdProvider 对应的 DB_VENDOR 实现会将 databaseId 设置为 DatabaseMetaData#getDatabaseProductName() 返回的字符串。 由于通常情况下这些字符串都非常长,而且相同产品的不同版本会返回不同的值,你可能想通过设置属性别名来使其变短:

 <!--
数据库厂商表示:mybatis提供用于跨数据库平台,用于根据不同的数据库调用不同SQL
type="DB_VENDOR" 利用数据库的厂商名称来区分
步骤:
    1.为需要跨越数据库设置不同的厂商名称
    2.编写不同的SQL   databaseId必须登录厂商的value
-->
 <databaseIdProvider type="DB_VENDOR">
     <property name="MySQL" value="mysql"/>
     <property name="Oracle" value="oracle" />
 </databaseIdProvider>

如上就配置了mysql和oracle的厂商

2-6-2、在EmpMapper.xml中使用数据库厂商标识

image.png 这样因为使用厂商不同导致sql语句不同锁产生的问题就可以解决。

2-7、通过xml设置增删改的相关参数

Insert, Update, Delete 元素的属性是一样的,如下:

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。
databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。

2-7-1、id 用于设置语句的唯一标识

id 同一个命名空间只能有一个唯一的id,除非有不同的databaseId,可以被用来引用这条语句。如果是接口绑定的是否一定要保证接口和方法名相同

2-7-2、parameterType用于传参

parameterType 用来设置该SQL的参数类型, 可以当它不存在,因为mybatis会根据接口方法的参数能够自动读取参数的类型

2-7-3、statementType 设置当前的statement

STATEMENT 代表jdbc的statement 不支持参数解析,不会设置
PREPARED 代表jdbc的PreparedStatement 支持参数解析, 默认的。
CALLABLE 代表jdbc的CallableStatement 执行存储过程

2-7-4、useGeneratedKeys获取插入后的主键值

这个参数一般用于mysql 或者sql server 等可以设置自增主键的数据库,像Oracle不支持自增主键的数据库则无意义。

一般我们在插入数据的时候如果想获取ID,就需要使用这个参数和keyProperty参数一起来使用。keyProperty可以将主键赋值到属性中。

2-7-4-1、获取主键

image.png 如上图,这样是无法获取当前插入数据库数据的主键值的,然后我们加上useGeneratedKeys以及keyProperty,如下:

image.png 这样就可以获取插入数据的ID值了。

2-7-4-2、数据库没有自增主键获取最新插入主键值

上面提到,如果是Oracle插入的时候是无法获取主键的,因此在插入的时候需要先查询一下当前数据表最大的id值,然后+1之后给新数据使用。

这样就需要使用selectKey 标签了,如下:

image.png

2-7-4-3、selectKey方式获得主键ID值

selectKey 可以在增删改之前或之后运行
order BEFORE|AFTER 设置在增删改之前或之后运行
keyProperty 将当前查询结果放到哪个pojo属性中
resultType 返回的数据类型

2-7-5、keyColumn获取多个字段的值

因为有可能存在组合主键的情况,指定获取其中哪一个字段

2-7-6、databaseId 数据库厂商ID

databaseId 用于配合databaseIdProvider 数据库厂商id 指定不同数据库下调用不同SQL,上面提到过,这边就不再次叙述了。

总结

1、本篇文章主要讲述了日志的简单相关配置,使用slf4j+logback。
2、以及mybatis配置文件中的settings相关各属性配置,大部分平时不用修改
3、propertiesp配置引入外部文件,以及在properties中直接配置属性
4、使用typeAliases 配置扫描PojoMapper,一般使用package进行处理

以上为mybatis中PojoMapper.xml的相关配置信息,对于select查询的配置方法,由于内容较多,后面的文章再进行叙述。