- properties
Mybatis核心配置文件包含了数据库连接的核心配置和mybatis框架的基础配置,是mybatis的核心描述文件。
下面逐一介绍该配置文件中的常用配置。
1.properties标签
该标签常用于定义mybatis环境的常量值,例如数据库连接的url,username,password等。
1)在标签中指定key和value
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="zhangdd" />
<property name="password" value="zd1991.." />
</properties>
然后在当前配置文件中的其他位置就可以利用key来引用对应的值。
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
2)引用外部popoerties文件到标签中
当不想在配置文件内部定义数据时,也可以用该标签引用一个外部的properties文件,mybatis会自动读取该文件中的内容并放入配置文件的全局范围。
dbConfig.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=zhangdd
password=zd1991..
在配置文件中就可以像这样来引用该properties文件:
<properties resource="dbConfig.properties"/>
获取其中的值的方式同上:
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
3)加载顺序
当properties文件,properties标签和Java代码中都存在相同的可以时,mybatis是按照一定的加载顺序去加载这些数据,并最后被加载的回覆盖先加载的数据。
加载顺序为:
(1)类路径下的properties文件。
(2)配置文件中的properties标签。
(3)java代码中的Properties对象。
2.settings
settings标签用于对mybatis运行时环境的一些重要参数的设置,利用该标签可以设置以下参数:
1)cacheEnabled 开启或禁用二级缓存
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
mybatis二级缓存被启用后,客户端就可以在sqlMapper中对具体的缓存产品,参数设置及具体的使用方式进行设置。默认情况下二级缓存是开启状态。
2)lazyLoadingEnabled 全局启用或禁用延时加载。
<setting name="lazyLoadingEnabled" value="true"/>
默认情况下开启全局延时加载。
3)aggressiveLazyLoading 当启用时, 有延迟加载属性的对象在被 调用时将会完全加载任意属性。否则, 每种属性将会按需要加载。
<setting name="multipleResultSetsEnabled" value="true"/>
默认为开启状态。
4)multipleResultSetsEnabled 允许或不允许多种结果集从一个单独 的语句中返回(需要适合的驱动)
<setting name="multipleResultSetsEnabled" value="true"/>
默认为允许。
5)useColumnLabel 使用列标签代替列名。 不同的驱动在这 方便表现不同。 参考驱动文档或充分测 试两种方法来决定所使用的驱动。
<setting name="useColumnLabel" value="true"/>
默认值为true。
6)useGeneratedKeys 允许 JDBC 支持生成的键。 需要适合的 驱动。 如果设置为 true 则这个设置强制 生成的键被使用, 尽管一些驱动拒绝兼 容但仍然有效(比如 Derby)
<setting name="useGeneratedKeys" value="false"/>
默认值为false。
7)autoMappingBehavior 指定 MyBatis 如何自动映射列到字段/ 属性。PARTIAL 只会自动映射简单, 没有嵌套的结果。FULL 会自动映射任 意复杂的结果(嵌套的或其他情况)
<setting name="autoMappingBehavior" value="PARTIAL"/>
类型包括:NONE, PARTIAL, FULL
默认为PARTIAL
8)defaultExecutorType 配置默认的执行器。SIMPLE 执行器没 有什么特别之处。REUSE 执行器重用 预处理语句。BATCH 执行器重用语句 和批量更新 .
<setting name="defaultExecutorType" value="SIMPLE"/>
类型包括:SIMPLE REUSE BATCH
默认为SIMPLE
9)defaultStatementTimeout 设置超时时间, 它决定驱动等待一个数 据库响应的时间
<setting name="defaultStatementTimeout" value="25"/>
默认没有设置。
3.typeAliases
类型别名,在mybatis的配置文件中通常需要制定某个类型的全名,方便起见,利用该标签可以配置某一类型的别名。
<typeAliases>
<typeAlias type="com.mybatis.test.entity.Pet" alias="Pet"/>
<typeAlias type="com.mybatis.test.entity.Department" alias="Department"/>
<typeAlias type="com.mybatis.test.entity.Employee" alias="Employee"/>
<typeAlias type="com.mybatis.test.handler.MyTypeHandler" alias="MyTypeHandler"/>
</typeAliases>
这样在SqlMapper.xml中引用类型的时候就可以使用类型的别名。
<!-- resultMap : POJO与数据库表字段映射 -->
<resultMap type="Pet" id="petMap">
...
也可以用mybatis提供的注解来为某个类制定别名:
@Alias("Pet")
public class Pet implements Serializable{
...
..
mybatis中提供了丰富的基本数据类型和常用的引用数据类型、集合等对应的别名,方便开发者描述配置文件:
基本数据类型:
_byte ---------------------------------------- byte
_short---------------------------------------- short
_int ------------------------------------------- int
_integer -------------------------------------- int
_long ----------------------------------------- long
_double --------------------------------------double
_float -----------------------------------------float
_boolean ------------------------------------boolean
引用数据类型:
string --------------------------------------- String
byte ----------------------------------------- Byte
long ----------------------------------------- Long
short ---------------------------------------- Short
int ------------------------------------------- Integer
integer -------------------------------------- Integer
double -------------------------------------- Double
float ----------------------------------------- Float
boolean ------------------------------------- Boolean
date ----------------------------------------- Date
decimal ------------------------------------- BigDecimal
bigdecimal --------------------------------- BigDecimal
object --------------------------------------- Object
map ------------------------------------------ Map
hashmap ------------------------------------ HashMap
list ---------------------------------------------List
arraylist -------------------------------------- ArrayList
collection ----------------------------------- Collection
iterator -------------------------------------- Iterator
4.typeHandlers
改标签用于自定义类型转换器,对一些特殊类型参数和结果集进行处理来实现数据库中数据类型和JavaBean中Java类型的指定方式的转换。
利用typeHandlers声明自定义类型转换器时,首先要编写自己的类型转器类,该类需要实现TypeHandler接口,并复写其中的方法,在对sql中的参数的赋值和取值处自定义处理方式。
eg:对控制做特殊处理
package com.mybatis.test.handler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
public class MyStringTypeHandler implements TypeHandler<String>{
@Override
public void setParameter(PreparedStatement ps, int i, String parameter,
JdbcType jdbcType) throws SQLException {
if("".equals(parameter) || "null".equals(parameter)
|| parameter == null || "NULL".equals(parameter)){
parameter = "blank";
}
ps.setString(i, parameter);
}
@Override
public String getResult(ResultSet rs, String columnName)
throws SQLException {
String result = rs.getString(columnName);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){
result = "blank";
}
return result;
}
@Override
public String getResult(ResultSet rs, int columnIndex) throws SQLException {
String result = rs.getString(columnIndex);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){
result = "blank";
}
return result;
}
@Override
public String getResult(CallableStatement cs, int columnIndex)
throws SQLException {
String result = cs.getString(columnIndex);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){
result = "blank";
}
return null;
}
}
定义好自己的结果处理器后需要在mybatis核心配置文件中用typeHandlers进行声明:
<typeHandlers>
<typeHandler javaType="string" jdbcType="VARCHAR" handler="com.mybatis.test.handler.MyStringTypeHandler"/></typeHandlers>
在此处声明自定义的类型处理器后,就可以在对?赋值和自定义结果集时对某个特定的字段指定自定义结果集,对其按照自定义的方式进行处理。
在结果集中指定类型转换器:
<resultMap type="com.mybatis.test.entity.Pet" id="petMap">
<!-- 制定结果构造器 -->
<constructor>
<!--
<idArg column="id" javaType="int"/>
-->
<!--
column ,
javaType,
jdbcType ,
typeHandler
-->
<arg column="name" javaType="string"/>
<arg column="species" javaType="string"/>
<arg column="sex" javaType="string"/>
</constructor>
<result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
<result column="species" property="species" javaType="string" jdbcType="VARCHAR" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
<result column="sex" property="sex" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
</resultMap>
这样在执行查询时我们将得到下面的结果:
<!-- custom type handler select test -->
<select id="cthSelect" resultMap="petMap">
select <include refid="column"/>
from pet
</select>
/**
* custom type handler test two
* */
@Test
public void cutomTypeHandlerTwo(){
session = sessionFactory.openSession();
List<Pet> pets = session.selectList("com.mybatis.test.entity.Pet.cthSelect");
Iterator<Pet> pi = pets.iterator();
while(pi.hasNext()){
System.out.println(pi.next());
}
}
Pet [name=bb, species=blank, sex=blank]
向表中插入一条记录,结果如下:
<!-- custom type handler insert test -->
<insert id="cthInsert" parameterType="hashmap">
insert into pet (<include refid="column"/>)
values (#{name,javaType=string,jdbcType=VARCHAR,typeHandler=com.mybatis.test.handler.MyStringTypeHandler},
#{species,typeHandler=com.mybatis.test.handler.MyStringTypeHandler},
#{sex,javaType=string,jdbcType=VARCHAR})
</insert>
/**
* custom type handler test
* */
@Test
public void customTypeHandler(){
session = sessionFactory.openSession();
Map<String,String> map = new HashMap<String,String>();
map.put("name", null);
map.put("species", null);
map.put("sex", null);
session.insert("com.mybatis.test.entity.Pet.cthInsert", map);
session.commit();
}
MyBatis提供了一部分类型处理器用于处理一些基本的数据类型和引用数据类型结果集:
BooleanTypeHandler
ByteTypeHandler
ShortTypeHandler
IntegerTypeHandler
LongTypeHandler
FloatTypeHandler
DoubleTypeHandler
BigDecimalTypeHandler
StringTypeHandler
ClobTypeHandler
NStringTypeHandler
NClobTypeHandler
ByteArrayTypeHandler
BlobTypeHandler
DateTypeHandler
DateOnlyTypeHandler
TimeOnlyTypeHandler
SqlTimestampTypeHandler
SqlDateTypeHandler
SqlTimeTypeHandler
ObjectTypeHandler
EnumTypeHandler
EnumOrdinalTypeHandler
5.objectFactory
mybatis的一个重要功能就是对结果集到bean对象的自动封装,创建bean对象的过程就是有ObjectFactory来完成的,在没有配置objectFactory标签时,mybatis使用默认的ObjectFactory的实现类DefaultBeanFactory来完成bean对象的创建,但是DefaultObjectFactory并没有做什么有意义的事情,所有我们也可以通过继承DefaultObjectFactory来覆盖其中的部分或全部方法,以实现对mybatis的扩展。
package com.mybatis.test.factory;
import java.util.List;
import java.util.Properties;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
@SuppressWarnings("serial")
public class CustomObjectFactory extends DefaultObjectFactory{
//调用bean对象的默认构造器
@Override
public <T> T create(Class<T> type) {
System.out.println("create object by auto constructor");
return super.create(type);
}
//当在sqlMapper中的bean映射中使用了<constroctor>标签时,
//创建bean对象时会调用该方法
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes,
List<Object> constructorArgs) {
// TODO Auto-generated method stub.print
System.out.println("create object by arg constructor");
return super.create(type, constructorArgTypes, constructorArgs);
}
@Override
public <T> boolean isCollection(Class<T> type) {
// TODO Auto-generated method stub
return super.isCollection(type);
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
super.setProperties(properties);
}
@Override
protected Class<?> resolveInterface(Class<?> type) {
// TODO Auto-generated method stub
return super.resolveInterface(type);
}
}
用objectFactory标签配置自定义的ObjectFactory:
<objectFactory type="com.mybatis.test.factory.CustomObjectFactory"/>
5.plugins
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的)
自定义插件:
package com.mybatis.test.plugin;
import java.util.Properties;
import java.util.concurrent.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
/**
* Mybatis plugin
* */
@Intercepts({@Signature(type = Executor.class,method="update",
args = {MappedStatement.class, Object.class})})
public class ExamplePlugin implements Interceptor{
@Override
public Object intercept(Invocation invocation) throws Throwable {
//实现拦截逻辑,通过proceed() 推进连接器
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//生成代理对象
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
}
}
配置自定义插件:
<plugins>
<plugin interceptor="com.mybatis.test.plugin.ExamplePlugin"/>
</plugins>
插件机制详解参考[追求极致的人]的博客
6.environments
该标签用于配置数据库连接的基础设置,例如事务管理器,连接池等。
mybatis可配置多个数据库连接,注意没一个数据库连接对应一个SqlSessionFactory,所以若想同时连接两个数据库,则需要建立两个mybatis的核心配置文件,并对应到相应的数据库。
下面是mybatis中一个environments配置示例:
<environments default="mysql_environment">
<environment id="mysql_environment">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="zhangdd" />
<property name="password" value="zd1991.." />
</dataSource>
</environment>
</environments>
其中一个environment对应一个数据库连接配置,可以利用environments的default属性来制定当前所使用的数据库连接配置,例如在开发时,连接测试数据库环境,在应用上线时连接生成环境,就可以实现进行配置,并利用default属性进行切换,使用起立很方便。
1)transactionManager
该标签用于设置事务管理器。mybatis提供了两种实物管理器:
JdbcTransaction(JDBC),ManagedTransaction(MANAGED),其中JdbcTransaction直接沿用了java-JDBC的事务管理机制,依赖于数据库连接来管理事务。而ManagedTransaction几乎什么都没有做,查看其源代码就可见一斑:
public void commit() throws SQLException {
// Does nothing
}
public void rollback() throws SQLException {
// Does nothing
}
public void close() throws SQLException {
if (this.closeConnection && this.connection != null) {
if (log.isDebugEnabled()) {
log.debug("Closing JDBC Connection [" + this.connection + "]");
}
this.connection.close();
}
}
mybatis的事务管理顶级接口是Transaction:
public interface Transaction {
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
两个实现类JdbcTransaction、ManagedTransaction,其中JdbcTransaction提供了设置事务是否自动提交的接口:
protected void setDesiredAutoCommit(boolean desiredAutoCommit)
若将mybatis与spring进行集成,则不需要配置事务管理器,因为spring的声明式事务处理以及将数据库操作的事务纳入管理范围。
2)dataSource
该标签用来配置数据源,一个简单的例子如下:
...
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="zhangdd" />
<property name="password" value="zd1991.." />
</dataSource>
...
mybatis提供了三种数据源的实现:UNPOOLED、POOLED、JNDI
UNPOOLED
该类型的数据源没有实现任何对数据库连接的缓存,而是已最原始的方法去连接数据库,即每次操作数据库都创建一个新的可用连接,然后释放掉。通常情况下需要配置以下选项:
driver – 这是 JDBC 驱动的 Java 类的完全限定名(如果你的驱动包含,它也不是 数据源类)。
url – 这是数据库的 JDBC URL 地址。
username – 登录数据库的用户名。
password – 登录数据库的密码。
defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
也可以通过driver.Xxxx的形式来制定与数据库先关的属性。
POOLED
这种类型的数据源是基本的JDBC数据库连接的连接池实现,是比较常用的一种数据源类型,除了上述的url、username、password、defaultTransactionIsolationLevel外,还可以对数据源的一个基本属性进行设置,具体如下:
poolMaximumActiveConnections:任意时间存在的活动连接数。默认为10。
poolMaximumIdleConnections:空闲连接数。
poolMaximumCheckoutTime:连接被强制返回到池中的超时时间。
poolPingQuery: 发送到数据的侦测查询,用来验证连接是否正常工作,并且准
备接受请求。默认是“NO PING QUERY SET”
poolPingEnabled – 这是开启或禁用侦测查询,默认为false。
JNDI
这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器, 容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这个数据源配置只需要两个属性:
initial_context:这个属性用来从初始上下文中寻找环境(也就是 initialContext.lookup(initial——context) 。这是个可选属性,如果被忽略,那么 data_source 属性将会直接以 initialContext 为背景再次寻找。
data_source:这是引用数据源实例位置的上下文的路径。它会以由 initial_context 查询返回的环境为背景来查找,如果 initial_context 没有返回结果时,直接以初始上下文为环境来查找。
env:和其他数据源配置相似, 它也可以通过名为 “env.” 的前缀直接向初始上下文发送属性。比如: env.encoding=UTF8在初始化之后,这就会以值“UTF8”向初始上下文的构造方法传递名为“encoding” 的属性。
也可以引用第三方的数据源,例如DBCP或C3P0,只需要将dateSource标签的type属性制定到特定的DataSource类就可以,例如:
<dataSource type="org.myproject.C3P0DataSourceFactory">
<property name="driver" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql:mydb"/>
<property name="username" value="postgres"/>
<property name="password" value="root"/>
</dataSource>
7.mappers
该标签用来引用Bean的sql映射文件,应用sql映射的方式有四种,分别是:
1)引入类路径下的xml文件
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
2)使用文件系统的绝对路径
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
3)使用接口是引用(对sql的映射也可以利用接口+注解的形式来完成)
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
4)使用包名来执行某些包下的所有映射
mappers>
<package name="org.mybatis.builder"/>
</mappers>