Loading

mybatis-03 Mybatis 配置

mybatis-03 Mybatis 配置

概述

虽说约定大于配置,已经是框架开发演进的方向,但掌握核心的配置往往能最大化地榨干框架的性能,满足我们的需求。目前对于 Mybatis 来说,我面临最大的一个问题就是:无法查看执行的 SQL 语句!这是致命的。但是,配置好 Mybatis 的日志实现后,就能在指定位置看到拼接出的 SQL 语句、查询结果、执行时间……

官网对配置的介绍都在这个页面上:https://mybatis.org/mybatis-3/zh/configuration.html


配置详解

环境配置(environments)

MyBatis 可以配置多套使用环境,但每个 SqlSessionFactory 实例只能选择一种环境。所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例……为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

如果忽略了环境参数,那么将会加载默认环境:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);

environments 元素定义了如何配置环境。

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

注意一些关键点:

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

其中较为陌生的概念大致有如下几条:

目前只需要记住的就是:

  • 在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")
  • Mybatis 默认连接方式是 pooled,事务处理器为 JDBC

属性(properties)

可以通过这个属性来引用外部配置文件,编写一个配置文件,后续可以按照${属性名}的格式取出

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?&useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=wal14.

要在 xml 配置文件中使用外部配置文件,只需要使用 properties 标签,并且用 resource 属性指明外部配置文件位置,之后就可以按照规约使用了:

<!--?xml version="1.0" encoding="UTF8" ?-->

<configuration>
<!--    引入外部配置文件-->
    <properties resource="db.properties">
        <!--        下面的配置会覆盖 db.properties 配置文件中对 url 的赋值-->
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?&useSSL=true&useUnicode=true&characterEncoding=utf8">
    </property></properties>

    <typealiases>
<!--        <typeAlias type="com.ermao.pojo.User" alias="User"/>-->
        <package name="com.ermao.pojo">
    </package></typealiases>

    <environments default="development">
        <environment id="development">
            <transactionmanager type="JDBC">
            <datasource type="POOLED">
                <property name="driver" value="${driver}">
                <property name="url" value="${url}">
                <property name="username" value="${username}">
                <property name="password" value="${password}">
            </property></property></property></property></datasource>
        </transactionmanager></environment>
    </environments>
    
    <mappers>
        <mapper resource="com/ermao/dao/UserMapper.xml">
    </mapper></mappers>
</configuration>

要在构建 SqlSessionFactory 对象的时候直接使用外部配置 properties,而非使用写定在 xml 文件中的 development 环境配置,可以这样:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);	// 没有使用 environment 配置而使用了 properties 里的外部配置

// ... 或者 ...

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);	// 两者都使用

对于同时使用外部配置文件和 xml 环境配置时的优先级,也就是说如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

  • 首先读取在 properties 元素体内指定的属性(也就是 xml 文件里明文配置的属性)。
  • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 xml 配置,意在减少全限定类名书写。例如:

<typealiases>
    <typealias type="com.ermao.pojo.User" alias="User">
    <typealias alias="Post" type="domain.blog.Post">
    <typealias alias="Section" type="domain.blog.Section">
	<typealias alias="Tag" type="domain.blog.Tag">
</typealias></typealias></typealias></typealias></typealiases>

但我们一般也不会按照上述方法行动,而是直接扫描一个包,包中的所有类都会以首字母小写和大写为别名(引用这些类的时候尽量用小写)。

另外可以使用Alias注解配合使用package来指定别名

@Alias("myUser")
public class User {
	private int id;
	private String name;
	private String pwd;
}
<select id="getUserList" resulttype="myUser">
    select * from mybatis.user
</select>

Mybatis 也为我们做好了 java 内置的一些基本数据类型的映射,要注意的是带下划线的别名映射的是基本类型,没有下划线的是对象类型:

_int --> int
int	--> Integer

_double --> double
double --> Double

设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

这个链接中的表格指定了各个设置的含义:https://mybatis.org/mybatis-3/zh/configuration.html#settings。挑几个迄今为止有所遇见和使用的进行简单的说明:

  • cacheEnabled
    • 是否启用缓存。
  • lazyLoadingEnabled
    • 是否懒加载
  • useGeneratedKeys
  • autoMappingBehavior
    • 指定 MyBatis 应如何自动映射列到字段或属性。
  • autoMappingUnknownColumnBehavior
    • 发现无法映射字段时的行为。
  • defaultExecutorType
    • 执行器模式,在执行 Batch 类型的语句的时候可以进行相关的配置。
  • mapUnderscoreToCamelCase
    • 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
  • localCacheScope
    • 缓存相关
  • callSettersOnNulls
    • 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。
  • logImpl
    • 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
    • 配置的值只能从候选项中选择,且大小写敏感。
  • useActualParamName
    • 允许使用方法签名中的名称作为 SQL 语句参数名称,并且通过#{参数名}获取得到。默认开启,这也是我们不需要在函数签名中使用 @Param 注解,但是仍然可以在 SQL 语句中通过参数名引用参数值的原因所在。
    • 参考:https://blog.csdn.net/qq_15038565/article/details/115414387

类型处理器(typeHandlers)

MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。具体的处理器见这张表:https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers。

这也是 ResultMap 结果集映射实现的依据之处,有非常高的灵活度。


插件(plugins)

拦截器,很容易让人同 MybatisPlus 中的拦截器联想起来,可以在 SQL 执行前后等其它时刻进行拦截并进行相应修改,MP 对 Mybatis 的部分扩展似乎就是从这里入手的。


映射器(mappers)

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

方式一:

<!-- 使用相对于类路径的资源引用 -->
<mappers>
    <mapper resource="com/ermao/dao/UserMapper.xml">
</mapper></mappers>

方式二

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper">
  <mapper class="org.mybatis.builder.BlogMapper">
  <mapper class="org.mybatis.builder.PostMapper">
</mapper></mapper></mapper></mappers>

这种方式要求映射器接口和映射器文件必须同名,且接口和xml文件必须在同一个包下。


方式三

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder">
</package></mappers>

这种方式要求映射器接口和映射器文件必须同名,且接口和xml文件必须在同一个包下。


关键对象的作用域和生命周期

理解我们之前讨论过的不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder:

  • 一旦创建了 SqlSessionFactory 就不再被需要。
  • 局部变量。

SqlSessionFactory:

  • 可以理解成一个连接池。
  • 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另外一个实例。
  • 所以它的最佳作用域为应用 scope。
  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 连接到连接池的 session。
  • 需要被开启和及时关闭。
  • 线程不安全,不应该被共享。
  • 最佳作用域为方法代码块。

日志

目前对于日志最迫切的需求就是:在控制台输出映射器中的 SQL 语句。

日志工厂

在配置详解的 settings 中提到了名为 logImpl 的选项,它的候选项目前只有下列几个,且默认是不实现:

  • SLF4J
  • LOG4J
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING
  • NO_LOGGING

如果没有特殊的要求(只是简单的控制台观察),可以使用标准日志工厂的实现,不需要额外的配置:

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING">
</setting></settings>

image-20210718165040963


Log4j 实现

  • og4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等。
  • 我们也可以控制每一条日志的输出格式。
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
  • 最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

先导入 Log4j 的依赖:

<dependency>
    <groupid>log4j</groupid>
    <artifactid>log4j</artifactid>
    <version>1.2.17</version>
</dependency>

编写配置文件,文件名为 log4j.properties,直接放置在 resources 目录下。

log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/ermao.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

可以直接使用了:

image-20211010203220566

posted @ 2021-10-10 20:35  槐下  阅读(78)  评论(0编辑  收藏  举报