Mybatis(三)【插件】【环境配置】【数据库厂商标识】【映射器】

305 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

XML配置-插件(plugins)

Mybatis实际是封装了JDBC,底层操作还是JDBC,JDBC的一套流程是:

  1. 获取连接
  2. 获取预编译对象
  3. 执行
  4. 获取结果集

同样的Mybatis在操作数据库时应该对应的有四个职能相似的API。Mybatis官网有四个如下:

  1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  2. ParameterHandler (getParameterObject, setParameters)
  3. ResultSetHandler (handleResultSets, handleOutputParameters)
  4. StatementHandler (prepare, parameterize, batch, update, query)

  我的理解是Mybatis通过这四个API来执行一条SQL,在这个过程中我们是可以修改Mybatis的默认行为的,而修改默认行为可能会造成框架不能正常使用,因为这些都是底层的核心封装。 ​

  如果你想改变Mybatis的默认行为,可以实现Interceptor接口,并指定要拦截的方法签名, 官网给出的示例:

// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  private Properties properties = new Properties();
  public Object intercept(Invocation invocation) throws Throwable {
    // implement pre processing if need
    Object returnObject = invocation.proceed();
    // implement post processing if need
    return returnObject;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
}
<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

通过插件的编写以及配置,该插件会拦截Executor示例中所有update方法代用,Exexcutor是执行底层迎神语句的对象,不清楚的可以看下Mybatis(一)中Mybatis架构图

小结:实际开发中,很少会去改变Mybatis默认的行为,当然除了通过插件的方式,还可以通过覆盖配置类来改变行为,具体做法是继承配置类,然后构建SqlSessionFactory时,将他传递到SqlSessionFactoryBuilder的build方法中即可

XML配置-环境配置(environments)

  这里的配置指的是数据源的配置,JDBC连接数据库需要四个参数,在Mybatis中这四个参数是配置在核心配置文件中的。在配置文件中是可以配置多套数据源的,如果不指定数据源的情况下会使用默认的数据源。

  上图中标签中有个default属性,当你不指定数据源时就会通过id去找到默认的数据源,需要注意的是,不指定数据源的情况下一定要保证默认的数据源id是存在的。  

  上图中配置了三个数据源,在创建SqlSessionFactory时,只能使用其中的一个数据源,指定的方式是SqlSessionFactoryBuilder的build重载方法,默认我们都是这么写的:

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

实际我们可以使用其他的重载方法来传入自己需要的数据源:

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

事务管理器

  使用JDBC在进行增删改的时候都需要commit()来提交连接,rollback()来回滚,在操作PL/SQL等可视化软件时在手动增删改后,需要点击左上角的一个提交按钮,这个按钮的作用等同于commit。Mybatis对于事务的管理有两种方式:

  1. JDBC:这个配置完全使用 JDBC 的提交和回滚,它依赖从数据源获得的连接来管理事务作用域。\

  2. MANAGED:这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。
    自定义Mybatis事物控制\

自定义Mybatis事务

  1. 实现TransactionFactory 类,用该类的全限定类型替换type属性的值就好了
public interface TransactionFactory {
  default void setProperties(Properties props) { // 从 3.5.2 开始,该方法为默认方法
    // 空实现
  }
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
  1. 实现Transaction 接口,在事务管理器实例化后,所有在 XML 中配置的属性将会被传递给 setProperties() 方法。
public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
  Integer getTimeout() throws SQLException;
}

小结:单独使用Mybatis时需要配置,使用Spring跟Mybatis的整合包时是不需要配置事务管理的。二者整合后,spring会有自带的配置类覆盖。

数据源

  Mybatis在核心配置文件中配置数据源时有三种选择,配置时在标签的type属性配上不同的数据源即可。

  1. 一般使用的是POOLED,这是一个池化的数据源,也就是我们常说的连接池,每个数据库连接使用完毕后不是关闭,而是放回池子中。 这样减少了创建连接的时间,并发下能够快速响应。通常配置数据源时,最简单的只需要driver,url,username,password四个属性即可,其他都是Mybatis默认的设置,实际Mybatis还提供了很多数据源属性,针对POOLED数据源还有以下配置:
defaultTransactionIsolationLevel默认的连接事务隔离级别
defaultNetworkTimeout等待数据库操作完成的的默认超时时间
poolMaximumActiveConnections可活动的连接数,Mybatis默认是10,如果你配置成0,那么Mybatis将不能使用
poolMaximumIdleConnections任意时间下,可以存在的空闲连接数
poolMaximumCheckoutTime被强制返回时,连接被检出的时间,默认是20秒
poolTimeToWait获取连接超时,会打印日志,并重新获取一个连接
poolMaximumLocalBadConnectionTolerance作用与每一个从池中获取数据源的线程,如果获取到坏连接,那么会重新回去连接,但是连接的数量不能超过该值与可活动连接数的和,默认值是3
poolPingQuery发送到数据库的侦测查询,用来检验连接是否正常工作并接受请求。默认是没有开启侦测查询
poolPingEnabled是否启动侦测查询。开启需要将poolPingQuery属性添加在一个可执行的SQL语句上(最好是非常快的SQL),默认值是false
poolPingConnectionsNotUsedFor配置poolPingQuery的频率。可以将超时时间配置的跟数据库一样,来避免不必要的侦测,默认值是0.也就是说所有连接每一时刻都被侦测,当然poolPingEnabled为true时适用。
  1. 第二个要介绍的数据源是UNPOOLED,这个数据源的每个连接都会被打开和关闭。速度比较慢,不管大项目小项目都不建议使用,专一一点,用第一种,第二种知道就好了。它的配置除了常规的几个数据源外,还有以下两个配置:
defaultTransactionIsolationLevel默认的连接事务隔离级别
defaultNetworkTimeout等待数据库操作完成的的默认超时时间

3.JNDI 这个数据源是为了能在EJB或应用服务器中使用,容器可以在外部配置输急眼,然后放在JNDI 的上下文中即可。它只需要配置两个属性即可:

initial_context会在配置的属性对应的值中寻找上下文
data_source引用数据源实例位置的上下文路径

XML配置-数据库厂商标识(databaseldProvider)

  Java中有定义了一套JDBC规范,把具体的实现交给数据库厂商自己实现,例如MySQL与Oracle的一些语法及命名都不太一致。Mybatis针对这个问题使用databasedId属性来区分不同数据库厂商的语句。当Mybatis加载到两条相同的语句时,Mybatis会加载匹配当前数据库databaseId的语句。 ​

当然Mybatis也可以支持多厂商特性,只需要在核心配置文件中配置如下代码即可。

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

自定义数据库厂商标识

// 实现ibatis包下的DatabaseidProvider即可
public interface DatabaseIdProvider {
  default void setProperties(Properties p) { // 从 3.5.2 开始,该方法为默认方法
    // 空实现
  }
  String getDatabaseId(DataSource dataSource) throws SQLException;
}

XML配置-映射器(mappers)

  映射器的作用是找到对应的SQL文件,在Mybatis入门的那篇文章中介绍到,映射文件实际上就是实现类。使用JDBC写法时,实现类实现接口,通过多态来找到对应的执行方法。那么Mybatis中的映射文件和接口是通过核心配置文件来建立联系的。Mybatis为我们提供了四种方式。

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

        <!-- 将包内的映射器接口实现全部注册为映射器 -->
        <!--<package name="com.evader.mapper"/>-->

        <!-- 使用映射器接口实现类的完全限定类名 -->
        <!--<mapper class="com.evader.mapper.UserMapper"></mapper>-->

         <!-- 使用完全限定资源定位符(URL) -->
        <mapper url="file:///D:/develop/idea/workspace/mybatis-review/mybatis-02/src/main/java/com/evader/mapper/UserMapper.xml"></mapper>
    </mappers>

小结:使用包的方式配置映射器是最方便的,完全限定资源定位符的意思是xml的绝对路径,那么file:///是固定的不写是找不到的。需要注意的是引用时注意是/分割还是.分割,对于笔者最后的绝对路径,切记不可换行,不信你自己换个试试?