建站知識(shí)互聯(lián)網(wǎng)整合營(yíng)銷推廣
MyBatis支持配置多個(gè)環(huán)境,這有助于將您的SQL映射應(yīng)用于多個(gè)數(shù)據(jù)庫,無論出于何種原因。例如,您可能希望為開發(fā)、測(cè)試和生產(chǎn)環(huán)境使用不同的配置?;蛘?#xff0c;您可能有多個(gè)共享相同模式的生產(chǎn)數(shù)據(jù)庫,并且想要在兩者上使用相同的SQL映射。有許多使用情況可以考慮。
有一件重要的事需要記住:雖然您可以配置多個(gè)環(huán)境,但在每個(gè)SqlSessionFactory實(shí)例中只能選擇一個(gè)環(huán)境。
因此,如果您想要連接到兩個(gè)數(shù)據(jù)庫,您需要?jiǎng)?chuàng)建兩個(gè)SqlSessionFactory實(shí)例,每個(gè)實(shí)例連接一個(gè)數(shù)據(jù)庫。對(duì)于三個(gè)數(shù)據(jù)庫,您需要三個(gè)實(shí)例,依此類推。這是非常容易記住的。
- 每個(gè)數(shù)據(jù)庫使用一個(gè)SqlSessionFactory實(shí)例。
要指定要構(gòu)建的環(huán)境,只需將其作為可選參數(shù)傳遞給SqlSessionFactoryBuilder。接受環(huán)境參數(shù)的兩種簽名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
?如果省略了環(huán)境參數(shù),則會(huì)加載默認(rèn)環(huán)境,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
environments元素定義了環(huán)境的配置。
<environments default="development"><environment id="development"><transactionManager type="JDBC"><property name="..." value="..."/></transactionManager><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment>
</environments>
請(qǐng)注意以下關(guān)鍵部分:
- 默認(rèn)環(huán)境ID(例如 default="development")。
- 每個(gè)定義環(huán)境的環(huán)境ID(例如 id="development")。
- 事務(wù)管理器的配置(例如 type="JDBC")。
- 數(shù)據(jù)源的配置(例如 type="POOLED")。
默認(rèn)環(huán)境和環(huán)境ID可以根據(jù)您的喜好進(jìn)行命名,只要確保默認(rèn)環(huán)境與其中一個(gè)環(huán)境ID匹配即可。
transactionManager
MyBatis包含兩種事務(wù)管理器類型(即type="[JDBC|MANAGED]"),它們分別是:
- JDBC – 這個(gè)配置直接使用JDBC的提交和回滾功能。它依賴于從數(shù)據(jù)源(dataSource)獲取的連接來管理事務(wù)的范圍。默認(rèn)情況下,它在關(guān)閉連接時(shí)啟用自動(dòng)提交,以保證與一些驅(qū)動(dòng)程序的兼容性。然而,對(duì)于某些驅(qū)動(dòng)程序來說,啟用自動(dòng)提交不僅是不必要的,而且還是一個(gè)昂貴的操作。因此,從版本3.5.10開始,您可以通過將“skipSetAutoCommitOnClose”屬性設(shè)置為true來跳過這一步驟。例如:?
<transactionManager type="JDBC"><property name="skipSetAutoCommitOnClose" value="true"/>
</transactionManager>
- ?MANAGED – 這個(gè)配置實(shí)際上幾乎不做任何操作。它不會(huì)提交或回滾連接。相反,它讓容器來管理事務(wù)的整個(gè)生命周期(例如JEE應(yīng)用服務(wù)器的上下文)。默認(rèn)情況下,它會(huì)關(guān)閉連接。然而,某些容器不希望出現(xiàn)這種情況,因此如果您需要阻止它關(guān)閉連接,請(qǐng)將“closeConnection”屬性設(shè)置為false。例如:
<transactionManager type="MANAGED"><property name="closeConnection" value="false"/>
</transactionManager>
?注意:如果您計(jì)劃將MyBatis與Spring一起使用,就不需要配置任何事務(wù)管理器,因?yàn)镾pring模塊會(huì)設(shè)置自己的事務(wù)管理器,覆蓋任何先前設(shè)置的配置。
這兩種事務(wù)管理器類型都不需要任何屬性。然而,它們都是類型別名,換句話說,您可以使用自己的完全限定類名或類型別名來引用您自己實(shí)現(xiàn)的TransactionFactory接口。
public interface TransactionFactory {default void setProperties(Properties props) { // Since 3.5.2, change to default method// NOP}Transaction newTransaction(Connection conn);Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
?在XML中配置的任何屬性都將在實(shí)例化后傳遞給setProperties()方法。您的實(shí)現(xiàn)還需要?jiǎng)?chuàng)建一個(gè)Transaction實(shí)現(xiàn),它也是一個(gè)非常簡(jiǎn)單的接口:
public interface Transaction {Connection getConnection() throws SQLException;void commit() throws SQLException;void rollback() throws SQLException;void close() throws SQLException;Integer getTimeout() throws SQLException;
}
使用這兩個(gè)接口,您可以完全自定義MyBatis如何處理事務(wù)。
dataSource
dataSource元素使用標(biāo)準(zhǔn)的JDBC DataSource接口配置JDBC連接對(duì)象的來源。
大多數(shù)MyBatis應(yīng)用程序?qū)词纠渲靡粋€(gè)dataSource。但是,這并不是必需的。需要注意的是,為了方便延遲加載(Lazy Loading),這個(gè)dataSource是必需的。
有三種內(nèi)置的數(shù)據(jù)源類型(type="[UNPOOLED|POOLED|JNDI]"):
UNPOOLED - 這個(gè)數(shù)據(jù)源的實(shí)現(xiàn)在每次請(qǐng)求時(shí)都會(huì)打開和關(guān)閉一個(gè)連接。雖然速度稍慢,但對(duì)于不需要立即可用連接性能的簡(jiǎn)單應(yīng)用程序來說,這是一個(gè)不錯(cuò)的選擇。不同的數(shù)據(jù)庫在這個(gè)性能方面也有所不同,所以對(duì)于某些數(shù)據(jù)庫來說,池化連接可能不太重要,這種配置會(huì)更理想。UNPOOLED數(shù)據(jù)源有以下屬性可以配置:
- driver - 這是JDBC驅(qū)動(dòng)程序的完全限定Java類名(如果您的驅(qū)動(dòng)程序包含一個(gè)DataSource類,則不是它)。
- url - 這是您數(shù)據(jù)庫實(shí)例的JDBC URL。
- username - 用于登錄的數(shù)據(jù)庫用戶名。
- password - 用于登錄的數(shù)據(jù)庫密碼。
- defaultTransactionIsolationLevel - 連接的默認(rèn)事務(wù)隔離級(jí)別??梢允褂靡韵骂A(yù)定義常量來設(shè)置:NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE。
- defaultNetworkTimeout - 默認(rèn)的網(wǎng)絡(luò)超時(shí)值,以毫秒為單位,用于等待數(shù)據(jù)庫操作完成。有關(guān)詳細(xì)信息,請(qǐng)參閱java.sql.Connection#setNetworkTimeout()的API文檔。
可選地,您還可以向數(shù)據(jù)庫驅(qū)動(dòng)程序傳遞屬性。要做到這一點(diǎn),將屬性前綴為 ?driver.
?,例如:
driver.encoding=UTF8
這將通過DriverManager.getConnection(url, driverProperties)方法向您的數(shù)據(jù)庫驅(qū)動(dòng)程序傳遞屬性編碼,屬性名稱為encoding,值為UTF8。
POOLED - 這是一種DataSource的實(shí)現(xiàn),它可以池化JDBC連接對(duì)象,以避免創(chuàng)建新的連接實(shí)例所需的初始連接和身份驗(yàn)證時(shí)間。這是并發(fā)Web應(yīng)用程序?qū)崿F(xiàn)最快響應(yīng)的常用方法。
除了上述的(UNPOOLED)屬性之外,還有許多其他屬性可用于配置POOLED數(shù)據(jù)源。以下是一些常用的屬性:
- 屬性
?poolMaximumActiveConnections
?表示同時(shí)存在的活動(dòng)(即正在使用)連接的數(shù)量。默認(rèn)值為10。 - 屬性
?poolMaximumIdleConnections
?表示同時(shí)存在的空閑連接的數(shù)量。 - 屬性
?poolMaximumCheckoutTime
?表示一個(gè)連接在被"check out"(即被獲取)之后可以持續(xù)存在的最長(zhǎng)時(shí)間,超過此時(shí)間將被強(qiáng)制返回到連接池。默認(rèn)值為20000毫秒(即20秒)。 - 屬性
?poolTimeToWait
?是一個(gè)低級(jí)設(shè)置,用于在獲取連接花費(fèi)異常長(zhǎng)的時(shí)間時(shí),給連接池一個(gè)機(jī)會(huì)打印日志狀態(tài)并重新嘗試獲取連接(以避免在連接池配置錯(cuò)誤的情況下永遠(yuǎn)靜默失敗)。默認(rèn)值為20000毫秒(即20秒)。 - 屬性
?poolMaximumLocalBadConnectionTolerance
?是關(guān)于線程容忍的壞連接數(shù)量的低級(jí)設(shè)置。如果一個(gè)線程獲取到一個(gè)壞連接,它可能還有另外一次機(jī)會(huì)重新嘗試獲取到另一個(gè)有效的連接。但重試次數(shù)不應(yīng)超過poolMaximumIdleConnections和poolMaximumLocalBadConnectionTolerance之和。默認(rèn)值為3(自3.4.5起)。 - 屬性
?poolPingQuery
?是發(fā)送給數(shù)據(jù)庫的Ping查詢,用于驗(yàn)證連接是否工作正常,并準(zhǔn)備接受請(qǐng)求。默認(rèn)值為"NO PING QUERY SET",這會(huì)導(dǎo)致大多數(shù)數(shù)據(jù)庫驅(qū)動(dòng)程序以良好的錯(cuò)誤消息失敗。 - 屬性
?poolPingEnabled
?用于啟用或禁用ping查詢。如果啟用,還必須設(shè)置具有有效SQL語句的poolPingQuery屬性(最好是一個(gè)非??斓牟樵?#xff09;。默認(rèn)值為false。 - 屬性
?poolPingConnectionsNotUsedFor
?配置poolPingQuery的使用頻率??梢詫⑵湓O(shè)置為與數(shù)據(jù)庫連接的典型超時(shí)時(shí)間相匹配,以避免不必要的ping查詢。默認(rèn)值為0(即每次都對(duì)所有連接進(jìn)行ping查詢,但前提是poolPingEnabled為true)。?
JNDI(Java命名和目錄接口)的這種DataSource實(shí)現(xiàn)是為與EJB或應(yīng)用服務(wù)器等容器一起使用而設(shè)計(jì)的。這些容器可以集中或外部地配置DataSource,并將對(duì)它的引用放置在JNDI上下文中。這種DataSource配置只需要兩個(gè)屬性:
- initial_context – 這個(gè)屬性用于從InitialContext中查找上下文(即initialContext.lookup(initial_context))。這個(gè)屬性是可選的,如果省略,則會(huì)直接在InitialContext中查找data_source屬性。
- data_source – 這是一個(gè)上下文路徑,用于找到對(duì)DataSource實(shí)例的引用。它會(huì)根據(jù)initial_context查找返回的上下文進(jìn)行查找,或者如果沒有提供initial_context,則會(huì)在InitialContext中直接進(jìn)行查找。?
與其他DataSource配置類似,可以通過在屬性前加上"env."的方式將屬性直接發(fā)送給InitialContext。例如:
env.encoding=UTF8
這將會(huì)在實(shí)例化InitialContext的構(gòu)造函數(shù)中將屬性"encoding"和值"UTF8"發(fā)送給InitialContext。
通過實(shí)現(xiàn)接口org.apache.ibatis.datasource.DataSourceFactory,您可以插入任何第三方的DataSource:
public interface DataSourceFactory {void setProperties(Properties props);DataSource getDataSource();
}
?org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory可以作為構(gòu)建新的數(shù)據(jù)源適配器的超類使用。例如,下面是將C3P0插入的代碼示例:
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {public C3P0DataSourceFactory() {this.dataSource = new ComboPooledDataSource();}
}
?要設(shè)置它,為您希望MyBatis調(diào)用的每個(gè)setter方法添加一個(gè)屬性。下面是一個(gè)連接到PostgreSQL數(shù)據(jù)庫的示例配置:
<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>
?