MyBatis系列三 配置(下)
五、ObjectFactory
当MyBatis在构建一个结果返回的时候,都会使用ObjectFactory (对象工厂)去构建 POJO,在MyBatis中可以定制自己的对象工厂。一般来说我们使用默认的ObjectFacotry 即可,MyBatis 中默认的 ObjectFacotry 是由 org.apache.ibatis.reflection.factory.DefaultObject Factory来提供服务的。在大部分的场景下我们都不用修改,如果要定制特定的工厂则需要进行配置,如代码清单3.25所示。
我们这里配置了一个对象工厂MyObjectFactory,对它的要求是实现ObjectFactory的接 口。实际上DefaultObjectFactory已经实现了 ObjectFactory的接口,我们可以通过继承 DefaultObjectFactory来简化编程。下面给出它的实现代码和测试结果,如代码清单3-26所示。
这里并没有实现额外的功能,只是做一下测试而已,如果定制需要自己编写里面的逻 辑。让我们运行一下,查看其运行的结果。
从运行的结果可以看出,首先,setProperties方法可以使得我们如何去处理设置进去的 属性,而create方法分别可以处理单个对象和列表对象。其次,我们配置的ObjectFactory 已经生效。注意,大部分的情况下,我们不需要使用自己配置的ObjectFactory,使用系统 默认的即可。
六、插件
插件(plugins)是比较复杂的,使用时要特别小心。使用插件将覆盖一些MyBatis内 部核心对象的行为,在没有了解MyBatis内部运行原理之前我们没有必要去讨论它,所以这里暂时不讨论。
七、environments 配置环境
1、概述
配置环境可以注册多个数据源(dataSource),每一个数据源分为两大部分:一个是数据库源的配置,另外一个是数据库事务(transactionManager)的配置。我们来看一个连接 池的数据源的配置,如代码清单3.27所示。
我们分析一下上面的配置。
- environments中的属性default,标明在缺省的情况下,我们将启用哪个数据源配置。
- environment元素是配置一个数据源的开始,属性id是设置这个数据源的标志,以便MyBatis上下文使用它。
- transactionManager配置的是数据库事务,其中type属性有3种配置方式。
- JDBC,釆用JDBC方式管理事务,在独立编码中我们常常使用。
- MANAGED,釆用容器方式管理事务,在JNDI数据源中常用。
- 自定义,由使用者自定义数据库事务管理办法,适用于特殊应用。
- property元素则是可以配置数据源的各类属性,我们这里配置了 autoCommit = false,则是要求数据源不自动提交。
- dataSource标签,是配置数据源连接的信息,type属性是提供我们对数据库连接方 式的配置,同样MyBatis提供这么几种配置方式:
- UNPOOLED,非连接池数据库(U叩ooledDataSource)o
- POOLED,连接池数据库(PooledDataSource)。
- JNDI, JNDI 数据源(JNDIDataSource)。
- 自定义数据源。
其中,配置的property元素,就是定义数据库的各类参数。
2、数据库事务
数据库事务MyBatis是交由SqlSession去控制的,我们可以通过SqlSession提交 (commit)或者回滚(rollback)o我们插入一个角色对象,如果成功就提交,否则就回滚, 如代码清单3-28所示。
代码清单3-28:数据库事务处理
try ( sqlSession = SqlSessionFactoryUtil.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
int count = roleMapper.insertRole(role); sqlSession.commit(); return count; }catch(Exception ex) ( sqlSession.rollback(); }finally ( sqlSession.close(); }
在大部分的工作环境下,我们都会使用Spring框架来控制它,这些内容将放到第8章 去讨论。
3、数据源
MyBatis内部为我们提供了 3种数据源的实现方式。
- UNPOOLED,非连接池,使用 MyBatis 提供的 org.apache.ibatis.datasource.u叩ooled. UnpooledDataSource 实现。
- POOLED,连接池,使用 MyBatis 提供的 o rg.apache.ibatis.datasource.pooled.PooledData Source 实现。
- JNDI,使用 MyBatis 提供的 org.apache.ibatis.datasource.jndi.JndiDataSourceFactory 来获取数据源。
我们只需要把数据源的属性type定义为UNPOOLED、POOLED> JNDI即可。
这3种实现方式比较简单,只需要配置参数即可,但有时候我们需要使用其他的数据源。 如果使用自定义数据源,它必须实现org.apache.ibatis.datasource.DataSourceFactory接口。比 如说我们可能要用DBCP数据源,这个时候我们需要自定义数据源,如代码清单3-29所示。
使用DBCP数据源需要我们提供一个类去配置它。我们按照下面的方法配置就可以使 用DBCP数据源了。
八、databaseldProvider数据库厂商标识
在相同数据库厂商的环境下,数据库厂商标识没有什么意义,在实际的应用中使用得 比较少,因为使用不同厂商数据库的系统还是比较少的。MyBatis可能会运行在不同厂商 的数据库中,它为此提供一个数据库标识,并提供自定义,它的作用在于指定SQL到对应 的数据库厂商提供的数据库中运行。
1、使用系统默认规则
MyBatis提供默认的配置规则,如代码清单3-30所示。
type="DB_VENDOR"是启动MyBatis内部注册的策略器。首先MyBatis会将你的配置读入Configuration类里面,在连接数据库后调用getDatabaseProductName()方法去获取数据库的信息,然后用我们配置的name值去做匹配来得到Databaseldo我们把这些配置到我们的例 子里,而我们的例子使用的正是MySQL数据库。这个时候,我们可以用下面的代码来获 得数据库的ID,显然结果就是MySQL。
我们也可以指定SQL在哪个数据库厂商执行,我们把Mapper的XML配置修改一下, 如代码清单3.31所示。
在多了一个databaseld属性的情况下,MyBatis将提供如下规则。
- 如果没有配置databaseldProvider标签,那么databaseld就会返回nulL
- 如果配置了 databaseldProvider标签,MyBatis就会用配置的name值去匹配数据库 信息,如果匹配得上就会设置databaseld,否则依旧为null。
- 如果Configuration的databaseld不为空,则它只会找到配置databaseld的SQL 语句。
- MyBatis会加载不带databaseld属性和带有匹配当前数据库databaseld属性的所有语 句。如果同时找到带有databaseld和不带databaseld的相同语句,则后者会被舍弃。
2、不使用系统默认规则
MyBatis也提供规则允许自定义,我们只要实现databaseldProvider接口,并且实现配 置即可,下面我们来看一个实例。
首先,写好我们自定义的规则类,如代码清单3.32所示。
代码清单 3-32: MydatabaseldProvider.java
package com.learn.chapters.databaseIdprovider; import java.sql.SQLException; import java.util.Properties; import javax.sql•DataSource; import org.apache•ibatis.mapping.DatabaseIdProvider; public class MydatabaseIdProvider implements DatabaseIdProvider{ private Properties properties = null; @Override public void setProperties(Properties properties) ( this.properties = properties; } @Override public String getDatabaseld(DataSource ds) throws SQLException { String dbName = ds.getConnection().getMetaData().getDatabaseProductName(); String dbld = (String)this.properties.get(dbName); return dbld; } }
其次,注册这个类到MyBatis上下文环境中,我们这样配置databaseldProvider标签, 如代码清单3-33所示。
代码清单 3-33:配置 databaseldProvider
<databaseIdProvider type="com.learn.chapter3.databaseIdprovider.MydatabaseIdProvider"> <property name="SQL Server" value="sqlserver"/> <property name="MySQL" value="mysql"/ > <property name="DB2" value="db2”/ > <property name="Oracle" value="oracle" /> </databaseIdProvider>
我们把type修改为我们自己实现的类,类里面setProperties方法的参数传递进去的将 会是我们在XML里面配置的信息,我们保存在类的变量properties里,方便以后读出。在 方法getDatabaseld中,传递的参数是数据库数据源,我们获取其名称,然后通过properties 的键值找到对应的databaseld。
如有特殊的要求,我们可以根据自己所需要的规则来编写databaseldProvider0配置 Mapper、使用规则和默认规则是一致的。
九、引入映射器的方法
映射器是MyBatis最复杂、最核心的组件。本节着重讨论如何引入映射器。而它的参 数类型、动态SQL、定义SQL、缓存信息等功能我们会在后面的几章专门讨论。
第2章讲解了映射器定义命名空间的方法,命名空间对应的是一个接口的全路径,而不是实现类,我们之后会讨论系统是如何现实的,现在我们只要知道使用这个接口能调度我们想要的SQL,并组装成为我们想要的结果即可。
首先,定义映射器的接口,如代码清单3.34所示。
代码清单3-34:定义Mapper接口
package com.learn.chapter3.mapper; import java.util.List; import com.learn.chapter3.po.Role; public interface RoleMapper { public Role getRole(Long id); }
其次,给出XML文件,如代码清单3.35所示。
引入映射器的方法很多,一般分为以下几种。
我们可以根据实际需要选择恰当的引入方法。