關於實體映射文件中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>