关于实体映射文件中namespace,以前的版本是可选的内容,现在被用来与接口绑定,也就是说把接口的实现转移到xml文件中来了,以后的维护会相当的方便。
第一篇的根据id查询学生的例子中,稍做修改:
建立StudentDAO接口
package cn.pf.ibatis.dao;
import java.util.List;
import cn.pf.ibatis.domain.Student;
public interface StudentDAO {
public Student queryStudentById(int id);
}
更改 student.xml中的mapper元素namespace属性
test.java中调用改为
Student student;
StudentDAO studentDAO =session.getMapper(StudentDAO.class);
try {
// student =
// (Student)session.selectOne(
// "cn.pf.ibatis.domain.StudentMapper.selectStudent",1);
student = studentDAO.queryStudentById(1);
} finally {
session.close();
}
System.out.println(student.toString());
生命周期
SqlSessionFactoryBuilder:
用于建立SqlSessionFactory的工具类,在创建SqlSessionFactory以后无需再让它存在于应用程序中,文档上说它的生命周期最好在局部方法内,所以在代码中看到
//根据资源文件内容建立session工厂
SqlSessionFactorysqlMapper =
newSqlSessionFactoryBuilder().build(reader);
没用引用指向 SqlSessionFactoryBuilder,会被gc回收。
SqlSessionFactory:
一旦建立,SqlSessionFactory就应该存在于整个应用程序生命周期,因为根据资源文件建立SqlSessionFactory对象需要很大的开销,所以保留在整个应用的生命周期中,最佳实践中推荐使用spring等依赖注入的框架从而管理SqlSessionFactory的单例生命周期。
SqlSession:
每一个线程都应该有自己的SqlSession对象,SqlSession对象不是线程安全的所以不应该被共享,如果使用web框架,应该将SqlSession的生命周期看作HTTP Request的生命周期,在返回HTTP Response的时候关闭SqlSession
引用
SqlSession session =sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
MapperInstances:
MapperInstances是绑定ibatis映射文件实现的接口,Mapper Instances的生命周期应该与SqlSession一样,但是Mapper Instances最好在一个方法中被创建,在方法结束时被销毁。
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}
配置文件
配置文件的层次结构如下:
•configuration
o properties
o settings
o typeAliases
o typeHandlers
o objectFactory
o plugins
o environments
environment
• transactionManager
• dataSource
o mappers
1 properties:
用来定义外部properties配置文件信息。比如
<properties resource="org/apache/ibatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</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>
那么username和password被替换成dev_user和F2Fa3!33TYyg,而drive和url属性将读取 config.properties中的内容从而取得具体值
properties还可以通过SqlSessionFactoryBuilder的build方法作为参数传入:
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory2 =
sqlSessionFactoryBuilder.build(reader, environment,props);
property加载顺序:
1、properties元素内部
2、外部properties文件
3、SqlSessionFactoryBuilder的build方法参数
也就是说,build方法参数中的properties优先级高于前两个,因为它是最后被加载,所以会覆盖前两种加载方法加载的properties值。
2 settings
Setting选项 | 描述 | 合法值 | 默认值 |
cacheEnabled | 是否使用全局缓存 | true|false | true |
lazyLoadingEnabled | 是否使用全局懒加载 | true|false | true |
multipleResultSetsEnabled | 是否允许返回多个结果集合(需要兼容的驱动) | true|false | true |
useColumnLabel | 使用列标签取代列名(不同驱动表现不同) | true|false | true |
useGeneratedKeys | 允许jdbc自动生成主键 | true|false | false |
defaultExecutorType | 配置默认执行方式 | SIMPLE| REUSE| BATCH | SIMPLE |
defaultStatementTimeout | 数据库超时时间 | Any positive integer | Not Set (null) |
例子:
<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="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
</settings>
3 typeAliases
java类别名
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
4 typeHandlers
Handler类型 | Java类型 | JDBC类型 |
BooleanTypeHandler | Boolean,boolean | Any compatible BOOLEAN |
ByteTypeHandler | Byte,byte | Any compatible NUMERIC or BYTE |
ShortTypeHandler | Short,short | Any compatible NUMERIC or SHORT INTEGER |
IntegerTypeHandler | Integer,int | Any compatible NUMERIC or INTEGER |
LongTypeHandler | Long,long | Any compatible NUMERIC or LONG INTEGER |
FloatTypeHandler | Float,float | Any compatible NUMERIC or FLOAT |
DoubleTypeHandler | Double,double | Any compatible NUMERIC or DOUBLE |
BigDecimalTypeHandler | BigDecimal | Any compatible NUMERIC or DECIMAL |
StringTypeHandler | String | CHAR,VARCHAR |
ClobTypeHandler | String | CLOB,LONGVARCHAR |
NStringTypeHandler | String | NVARCHAR,NCHAR |
NClobTypeHandler | String | NCLOB |
ByteArrayTypeHandler | byte[] | Any compatible byte stream type |
BlobTypeHandler | byte[] | BLOB,LONGVARBINARY |
DateTypeHandler | Date(java.util) | TIMESTAMP |
DateOnlyTypeHandler | Date(java.util) | DATE |
TimeOnlyTypeHandler | Date(java.util) | TIME |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP |
SqlDateTypeHadler | Date(java.sql) | DATE |
SqlTimeTypeHandler | Time(java.sql) | TIME |
ObjectTypeHandler | Any | OTHER,or unspecified |
也可以通过实现TypeHandler接口来实现自定义的类型转换器
//ExampleTypeHandler.java
public class ExampleTypeHandlerimplements TypeHandler {
public void setParameter(PreparedStatement ps, int i,
Object parameter,JdbcType jdbcType)
throws SQLException{
ps.setString(i,(String) parameter);
}
public Object getResult(
ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName);
}
public Object getResult(CallableStatementcs, int columnIndex)
throws SQLException{
returncs.getString(columnIndex);
}
}
// MapperConfig.xml
<typeHandlers>
<typeHandler handler=
"org.apache.ibatis.example.ExampleTypeHandler"
javaType="string" jdbcType="VARCHAR"/>
</typeHandlers>
这样会覆盖原来ibatis默认的string varchar转换器
5 objectFactory
ibatis使用objectFactory去创建result object的实例对象,这里可以自己继承DefaultObjectFactory类实现自己的ObjectFactory
//ExampleObjectFactory.java
public class ExampleObjectFactoryextends DefaultObjectFactory {
public Object create(Class type){
return super.create(type);
}
public Object create(Class type, ListconstructorArgTypes,
ListconstructorArgs) {
return super.create(type, constructorArgTypes,constructorArgs);
}
public void setProperties(Properties properties) {
super.setProperties(properties);
}
}
//MapperConfig.xml
<objectFactory type="org.apache.ibatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
6 plugins
ibatis允许插件截断以下方法调用
Executor(update,query,flushStatements,commit,rollback,getTransaction,close,isClosed)
ParameterHandler(getParameterObject,setParameters)
ResultSetHandler(handleResultSets,handleOutputParameters)
StatementHandler(prepare,parameterize,batch,update,query)
必须在理解这些方法的基础上很小心的使用插件,不然很容易破坏ibatis的核心
//ExamplePlugin.java
@Intercepts({@Signature(type= Executor.class, method = "update",
args= {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocationinvocation) throws Throwable {
return invocation.proceed();
}
public Object plugin(Object target){
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
//MapperConfig.xml
<plugins>
<plugin interceptor="org.apache.ibatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
7 environments
这个是ibatis 3非常好的一个配置,允许配置多个不懂运行环境参数,不过每个SqlSessionFactory只可以在一种环境下被创建。
利用SqlSessionFactory的build函数
SqlSessionFactoryfactory =
sqlSessionFactoryBuilder.build(reader,environment);
SqlSessionFactoryfactory =
sqlSessionFactoryBuilder.build(reader,environment,properties);
如果不知名environment参数,则应用默认的环境参数
SqlSessionFactoryfactory = sqlSessionFactoryBuilder.build(reader);
SqlSessionFactoryfactory =
sqlSessionFactoryBuilder.build(reader,properties);
xml中如下配置:
<environmentsdefault="MySQL">
<environment id="MySQL">
<transactionManager type="JDBC" />
<dataSourcetype="POOLED">
<property name="driver"value="${driver}" />
<property name="url" value="${url}"/>
<property name="username"value="${username}" />
<property name="password"value="${password}" />
</dataSource>
</environment>
</environments>
几个注意点:
默认environment id:development
事务控制类型:JDBC
JDBC:根据jdbc控制事务的提交和回滚
MANAGED:将事务控制转交给容器
数据源类型:POOLED
UNPOOLED:不使用池技术,在请求到来时直接打开或者关闭数据库连接
必须配置的参数:driver、url、username、password
可选参数:使用driver.xxx来配置,如:driver.encoding=UTF8
POOLED:使用数据库连接池
类型 | 描述 | 默认值 |
poolMaximumActiveConnections | 同一时间内最大连接数 | 10 |
poolMaximumIdleConnections | 连接最大空闲数目 |
|
poolMaximumCheckoutTime | 连接被每个任务占用的最大时间 | 20000ms |
poolTimeToWait | 连接池中无可用连接时,线程的等待时间 | 20000ms |
poolPingQuery | 数据库连接状态检测语句,类似于ping的功能 | NO PING QUERY SET |
poolPingEnabled | 是否允许ping检测 | false |
poolPingConnectionsNotUsedFor | 对超过指定空闲时间的数据库连接进 行状态监测 | 0 (必须在poolPingEnabled设置true情况下) |
JNDI:
initial_context:可选
data_source:JNDI数据库名称.使用env.xxx配置可选参数,
如:env.encoding=UTF8
8 mappers
配置实体映射文件的路径
<mappers>
<mapper resource="org/apache/ibatis/builder/AuthorMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/BlogMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/PostMapper.xml"/>
</mappers>