這是我們在上一篇文章中用到的:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<!-- 別名 包以其子包下所有類 頭字母大小都行-->
<typeAliases>
<!-- <typeAlias type="com.frank.dao.model" alias="User"/> -->
<package name="com.frank.dao.model"/>
</typeAliases>
<!-- 和spring整合后 environments配置將廢除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事務(wù)管理 -->
<transactionManager type="JDBC"/>
<!-- 數(shù)據(jù)庫連接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_test?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- Mapper的位置 Mapper.xml 寫Sql語句的文件的位置 -->
<mappers>
<!-- 1.resource方式
在UserMapper.xml,定義namespace為mapper接口的地址颤枪,映射文件通過namespace找到對應(yīng)的mapper接口文件
-->
<!-- <mapper resource="com.frank.dao.mapper/UserMapper.xml" />-->
<!--2. class方式 class:指定 mapper接口的地址
遵循規(guī)則:將mapper.xml和mapper.java文件放在一個目錄 且文件名相同-->
<!-- <mapper class="com.frank.dao.mapper.UserMapper"/> -->
<!--3. 批量mapper掃描
遵循規(guī)則:將mapper.xml和mapper.java文件放在一個目錄 且文件名相同
-->
<package name="com.frank.dao.mapper"/>
</mappers>
</configuration>
MyBatis 的 XML 配置文件包含了影響 MyBatis 行為甚深的設(shè)置和屬性信息。XML 文檔的高層級結(jié)構(gòu)如下:
- configuration 配置
- properties 屬性
- settings 設(shè)置
- typeAliases 類型命名
- typeHandlers 類型處理器
- objectFactory 對象工廠
- plugins 插件
- environments 環(huán)境
- 映射器
properties
這些是外部化的,可替代的屬性每币,這些屬性也可以配置在典型的 Java 屬性配置文件中先壕,或者通過 properties 元素的子元素來傳遞。例如:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
其中的屬性就可以在整個配置文件中使用念祭,使用可替換的屬性來實現(xiàn)動態(tài)配置兑宇。比如:
<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 將會由 properties 元素中設(shè)置的值來替換。driver 和url 屬性將會從包含進(jìn)來的 config.properties 文件中的值來替換粱坤。這里提供很多配置的選項隶糕。
屬性也可以被傳遞到 SqlSessionBuilder.build()方法中。例如:
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, environment, props);
如果在這些地方站玄,屬性多于一個的話枚驻,MyBatis 按照如下的順序加載它們:
- 在 properties 元素體內(nèi)指定的屬性首先被讀取。
- 從類路徑下資源或 properties 元素的 url 屬性中加載的屬性第二被讀取株旷,它會覆蓋已經(jīng)存在的完全一樣的屬性再登。
- 作為方法參數(shù)傳遞的屬性最后被讀取,它也會覆蓋任一已經(jīng)存在的完全一樣的屬性晾剖,這些屬性可能是從 properties 元素體內(nèi)和資源/url 屬性中加載的锉矢。因此,最高優(yōu)先級的屬性是那些作為方法參數(shù)的齿尽,然后是資源/url 屬性沽损,最后是 properties元素中指定的屬性。
Settings
這些是極其重要的調(diào)整循头,它們會修改 MyBatis 在運行時的行為方式绵估。下面這個表格描述了設(shè)置信息,它們的含義和默認(rèn)值卡骂。
一個設(shè)置信息元素的示例国裳,完全的配置如下所示:
<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="enhancementEnabled" value="false"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
</settings>
typeAliases
類型別名是為 Java 類型命名一個短的名字。它只和 XML 配置有關(guān)全跨,只用來減少類完全限定名的多余部分缝左。例如:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
使用這個配置,“Blog”可以任意用來替代“domain.blog.Blog”所使用的地方浓若。
對于普通的 Java 類型渺杉,有許多內(nèi)建的類型別名。它們都是大小寫不敏感的七嫌,由于重載的名字少办,要注意原生類型的特殊處理。
無論是 MyBatis 在預(yù)處理語句中設(shè)置一個參數(shù)诵原,還是從結(jié)果集中取出一個值時英妓,類型處理器被用來將獲取的值以合適的方式轉(zhuǎn)換成 Java 類型挽放。下面這個表格描述了默認(rèn)的類型處理器。
作為代碼存儲(而不是索引)蔓纠。
你可以重寫類型處理器或創(chuàng)建你自己的類型處理器來處理不支持的或非標(biāo)準(zhǔn)的類型辑畦。要這樣做的話,簡單實現(xiàn) TypeHandler 接口(org.mybatis.type)腿倚,然后映射新的類型處理器類到Java 類型纯出,還有可選的一個 JDBC 類型。例如:
// ExampleTypeHandler.java
public class ExampleTypeHandler implements 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(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getString(columnIndex);
}
}
// MapperConfig.xml
<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR"
handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
使用這樣的類型處理器將會覆蓋已經(jīng)存在的處理 Java 的 String 類型屬性和 VARCHAR參數(shù)及結(jié)果的類型處理器敷燎。要注意 MyBatis 不會審視數(shù)據(jù)庫元信息來決定使用哪種類型暂筝,所以你必須在參數(shù)和結(jié)果映射中指定那是 VARCHAR 類型的字段,來綁定到正確的類型處理器上硬贯。這是因為 MyBatis 直到語句被執(zhí)行都不知道數(shù)據(jù)類型的這個現(xiàn)實導(dǎo)致的焕襟。
objectFactory
MyBatis 每次創(chuàng)建結(jié)果對象新的實例時,它使用一個 ObjectFactory 實例來完成饭豹。如果參數(shù)映射存在鸵赖,默認(rèn)的 ObjectFactory 不比使用默認(rèn)構(gòu)造方法或帶參數(shù)的構(gòu)造方法實例化目標(biāo)類做的工作多。如果你想重寫默認(rèn)的 ObjectFactory拄衰,你可以創(chuàng)建你自己的它褪。比如:
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
public Object create(Class type) {
return super.create(type);
}
public Object create(Class type,List<Class> constructorArgTypes,
List<Object> constructorArgs) {
return super.create(type, constructorArgTypes,
constructorArgs);
}
public void setProperties(Properties properties) {
super.setProperties(properties);
}
}
// MapperConfig.xml
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
ObjectFactory 接口非常簡單。它包含兩個用于創(chuàng)建的方法翘悉,一個是默認(rèn)構(gòu)造方法茫打,另外一個是處理帶參數(shù)的構(gòu)造方法。最終镐确,setProperties 方法可以被用來配置 ObjectFactory包吝。在初始化你的ObjectFactory實例后饼煞,objectFactory元素體中定義的屬性會被傳遞給setProperties方法源葫。
plugins
MyBatis 允許你在某一點攔截已映射語句執(zhí)行的調(diào)用。默認(rèn)情況下砖瞧,MyBatis 允許使用插件來攔截方法調(diào)用:
- Executor
(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)- ParameterHandler
(getParameterObject, setParameters)- ResultSetHandler
(handleResultSets, handleOutputParameters)- StatementHandler
(prepare, parameterize, batch, update, query)
這些類中方法的詳情可以通過查看每個方法的簽名來發(fā)現(xiàn)息堂,而且它們的源代碼存在于MyBatis 的發(fā)行包中。你應(yīng)該理解你所覆蓋方法的行為块促,假設(shè)你所做的要比監(jiān)視調(diào)用要多龄句。
如果你嘗試修改或覆蓋一個給定的方法又兵,你可能會打破 MyBatis 的核心。這是低層次的類和方法,要謹(jǐn)慎使用插件谱净。
使用插件是它們提供的非常簡單的力量。簡單實現(xiàn)攔截器接口谴仙,要確定你想攔截的指定簽名央星。
// ExamplePlugin.java
@Intercepts({@Signature(type= Executor.class,method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) 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.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
上面的插件將會攔截在 Executor 實例中所有的“update”方法調(diào)用啃洋,它也是負(fù)責(zé)低層次映射語句執(zhí)行的內(nèi)部對象。
environments
MyBatis 可以配置多種環(huán)境屎鳍。這會幫助你將 SQL 映射應(yīng)用于多種數(shù)據(jù)庫之中宏娄。例如,你也許為開發(fā)要設(shè)置不同的配置逮壁,測試和生產(chǎn)環(huán)境孵坚。或者你可能有多種生產(chǎn)級數(shù)據(jù)庫卻共享相同的模式窥淆,所以你會想對不同數(shù)據(jù)庫使用相同的 SQL 映射卖宠。這種用例是很多的。
要記得一個很重要的問題:你可以配置多種環(huán)境忧饭,但你只能為每個SqlSessionFactory實例選擇一個逗堵。
所以,如果你想連接兩個數(shù)據(jù)庫眷昆,你需要創(chuàng)建兩個 SqlSessionFactory 實例蜒秤,每個數(shù)據(jù)庫對應(yīng)一個。而如果是三個數(shù)據(jù)庫亚斋,你就需要三個實例作媚,以此類推。記憶起來很簡單:
? 個 每個數(shù)據(jù)庫對應(yīng)一個 SqlSessionFactory
為了明確創(chuàng)建哪種環(huán)境帅刊,你可以將它作為可選的參數(shù)傳遞給 SqlSessionFactoryBuilder纸泡。
可以接受環(huán)境配置的兩個方法簽名是:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,
environment,properties);
如果環(huán)境被忽略,那么默認(rèn)環(huán)境將會被加載赖瞒,如下進(jìn)行:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);
環(huán)境元素定義了如何配置環(huán)境女揭。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="{url}"/>
<property name="username" value="{password}"/>
</dataSource>
</environment>
</environments>
注意這里的關(guān)鍵部分:
? 默認(rèn)的環(huán)境 ID(比如:default=”development”)。
? 每個 environment 元素定義的環(huán)境 ID(比如:id=”development”)栏饮。
? 事務(wù)管理器的配置(比如:type=”JDBC”)吧兔。
覆蓋配置類
除了用插件來修改 MyBatis 核心行為之外,你也可以完全覆蓋配置類袍嬉。簡單擴(kuò)展它境蔼,
然后覆蓋其中的任意方法,之后傳遞它到 sqlSessionFactoryBuilder.build(myConfig)方法
的調(diào)用伺通。這可能會嚴(yán)重影響 MyBatis 的行為箍土,所以要小心。
? 數(shù)據(jù)源的配置(比如:type=”POOLED”)罐监。
默認(rèn)的環(huán)境和環(huán)境 ID 是自我解釋的吴藻。你可以使用你喜歡的名稱來命名,只要確定默認(rèn)
的要匹配其中之一弓柱。
transactionManager
在 MyBatis 中有兩種事務(wù)管理器類型(也就是 type=”[JDBC|MANAGED]”):
? JDBC – 這個配置直接簡單使用了 JDBC 的提交和回滾設(shè)置沟堡。它依賴于從數(shù)據(jù)源得
到的連接來管理事務(wù)范圍疮鲫。
? MANAGED – 這個配置幾乎沒做什么。它從來不提交或回滾一個連接弦叶。而它會讓
容器來管理事務(wù)的整個生命周期(比如 Spring 或 JEE 應(yīng)用服務(wù)器的上下文)俊犯。默認(rèn)
情況下它會關(guān)閉連接。然而一些容器并不希望這樣伤哺,因此如果你需要從連接中停止
它燕侠,將 closeConnection 屬性設(shè)置為 false。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
這兩種事務(wù)管理器都不需要任何屬性立莉。然而它們都是類型別名绢彤,要替換使用它們,你需
要放置將你自己的類的完全限定名或類型別名蜓耻,它們引用了你對 TransacFactory 接口的實現(xiàn)
類茫舶。
public interface TransactionFactory {
void setProperties(Properties props);
Transaction newTransaction(Connection conn, boolean autoCommit);
}
任何在 XML 中配置的屬性在實例化之后將會被傳遞給 setProperties()方法。你的實現(xiàn)類
需要創(chuàng)建一個事務(wù)接口的實現(xiàn)刹淌,這個接口也很簡單:
public interface Transaction {
Connection getConnection();
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
使用這兩個接口饶氏,你可以完全自定義 MyBatis 對事務(wù)的處理。
dataSsource
dataSource 元素使用基本的 JDBC 數(shù)據(jù)源接口來配置 JDBC 連接對象的資源有勾。
? 許多 MyBatis 的應(yīng)用程序?qū)词纠械睦觼砼渲脭?shù)據(jù)源疹启。然而它并不是必須的。
要知道為了方便使用延遲加載蔼卡,數(shù)據(jù)源才是必須的喊崖。
有三種內(nèi)建的數(shù)據(jù)源類型(也就是 type=”???”):
UNPOOLED – 這個數(shù)據(jù)源的實現(xiàn)是每次被請求時簡單打開和關(guān)閉連接。它有一點慢雇逞,
這是對簡單應(yīng)用程序的一個很好的選擇荤懂,因為它不需要及時的可用連接。不同的數(shù)據(jù)庫對這
個的表現(xiàn)也是不一樣的塘砸,所以對某些數(shù)據(jù)庫來說配置數(shù)據(jù)源并不重要节仿,這個配置也是閑置的。
UNPOOLED 類型的數(shù)據(jù)源僅僅用來配置以下 5 種屬性:
? driver – 這是 JDBC 驅(qū)動的 Java 類的完全限定名(如果你的驅(qū)動包含的有谣蠢,它也
不是數(shù)據(jù)源類)粟耻。
? url – 這是數(shù)據(jù)庫的 JDBC URL 地址查近。
? username – 登錄數(shù)據(jù)庫的用戶名眉踱。
? password – 登錄數(shù)據(jù)庫的密碼。
? defaultTransactionIsolationLevel – 默認(rèn)的連接事務(wù)隔離級別霜威。
作為可選項谈喳,你可以傳遞數(shù)據(jù)庫驅(qū)動的屬性。要這樣做戈泼,屬性的前綴是以“driver.”開
頭的婿禽,例如:
? driver.encoding=UTF8
這 樣 就 會 傳 遞 以 值 “ UTF8 ” 來 傳 遞 “ encoding ” 屬 性 赏僧, 它 是 通 過
DriverManager.getConnection(url,driverProperties)方法傳遞給數(shù)據(jù)庫驅(qū)動。
POOLED – 這是 JDBC 連接對象的數(shù)據(jù)源連接池的實現(xiàn)扭倾,用來避免創(chuàng)建新的連接實例
時必要的初始連接和認(rèn)證時間淀零。這是一種當(dāng)前 Web 應(yīng)用程序用來快速響應(yīng)請求很流行的方
法。
除了上述(UNPOOLED)的屬性之外膛壹,還有很多屬性可以用來配置 POOLED 數(shù)據(jù)源:
? poolMaximumActiveConnections – 在任意時間存在的活動(也就是正在使用)連
接的數(shù)量驾中。默認(rèn)值:10
? poolMaximumIdleConnections – 任意時間存在的空閑連接數(shù)。
? poolMaximumCheckoutTime – 在被強制返回之前模聋,池中連接被檢查的時間肩民。默認(rèn)
值:20000 毫秒(也就是 20 秒)
? poolTimeToWait – 這是給連接池一個打印日志狀態(tài)機會的低層次設(shè)置,還有重新
嘗試獲得連接链方,這些情況下往往需要很長時間(為了避免連接池沒有配置時靜默失
敵痔怠)。默認(rèn)值:20000 毫秒(也就是 20 秒)
? poolPingQuery – 發(fā)送到數(shù)據(jù)的偵測查詢祟蚀,用來驗證連接是否正常工作工窍,并且準(zhǔn)備
接受請求。默認(rèn)是“NO PING QUERY SET”前酿,這會引起許多數(shù)據(jù)庫驅(qū)動連接由一
個錯誤信息而導(dǎo)致失敗移剪。
? poolPingEnabled – 這是開啟或禁用偵測查詢。如果開啟薪者,你必須用一個合法的
SQL 語句(最好是很快速的)設(shè)置 poolPingQuery 屬性纵苛。默認(rèn)值:false。
? poolPingConnectionsNotUsedFor – 這是用來配置 poolPingQuery 多次時間被用一
次言津。這可以被設(shè)置匹配標(biāo)準(zhǔn)的數(shù)據(jù)庫連接超時時間攻人,來避免不必要的偵測。默認(rèn)值:
0(也就是所有連接每一時刻都被偵測-但僅僅當(dāng) poolPingEnabled 為 true 時適用)悬槽。
JNDI – 這個數(shù)據(jù)源的實現(xiàn)是為了使用如 Spring 或應(yīng)用服務(wù)器這類的容器怀吻,容器可以集
中或在外部配置數(shù)據(jù)源,然后放置一個 JNDI 上下文的引用初婆。這個數(shù)據(jù)源配置只需要兩個屬
性:
? initial_context – 這 個 屬 性 用 來 從 初 始 上 下 文 中 尋 找 環(huán) 境 ( 也 就 是
initialContext.lookup(initial——context))蓬坡。這是個可選屬性,如果被忽略磅叛,那么
data_source 屬性將會直接以 initialContext 為背景再次尋找屑咳。
? data_source – 這是引用數(shù)據(jù)源實例位置的上下文的路徑。它會以由 initial_context
查詢返回的環(huán)境為背景來查找弊琴,如果 initial_context 沒有返回結(jié)果時兆龙,直接以初始
上下文為環(huán)境來查找。
和其他數(shù)據(jù)源配置相似敲董,它也可以通過名為“env.”的前綴直接向初始上下文發(fā)送屬性紫皇。
比如:
? env.encoding=UTF8
在初始化之后慰安,這就會以值“UTF8”向初始上下文的構(gòu)造方法傳遞名為“encoding”
的屬性。
mappers
既然 MyBatis 的行為已經(jīng)由上述元素配置完了聪铺,我們現(xiàn)在就要定義 SQL 映射語句了化焕。
但是,首先我們需要告訴 MyBatis 到哪里去找到這些語句铃剔。Java 在這方面沒有提供一個很好
的方法锣杂,所以最佳的方式是告訴 MyBatis 到哪里去找映射文件。你可以使用相對于類路徑的
資源引用番宁,或者字符表示元莫,或 url 引用的完全限定名(包括 file:///URLs)。例如:
// 使用相對于類路徑的資源
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
// 使用完全限定路徑
<mappers>
<mapper url="file:///var/sqlmaps/AuthorMapper.xml"/>
<mapper url="file:///var/sqlmaps/BlogMapper.xml"/>
<mapper url="file:///var/sqlmaps/PostMapper.xml"/>
</mappers>