一、environments配置信息:
environments的作用是用來配置數據庫信息,可以配置多個,其有兩個可配的子元素,分別是:事務管理器transactionManager和數據源dataSource,先看一下我配置的例子:
1 <!-- 環境模式:development開發模式 work工作模式 --> 2 <environments default="development"> 3 <!--環境變量 --> 4 <environment id="development"> 5 <!--事務管理器 --> 6 <transactionManager type="JDBC" /> 7 <!--數據源 --> 8 <dataSource type="POOLED"> 9 <property name="driver" value="${db.driver}" /> 10 <property name="url" value="${db.url}" /> 11 <property name="username" value="${db.username}" /> 12 <property name="password" value="${db.pwd}" /> 13 </dataSource> 14 </environment> 15 </environments>
配置項說明:
1⃣️environments-default:該屬性指定當前的環境,有development和work兩種選擇,默認是development開發模式;
2⃣️environment-id:該屬性是每個environment定義的環境,也有development和work兩種選擇,默認是development開發模式;
3⃣️transactionManager-type:該屬性是配置事務管理器的類型,mybatis中有JDBC和MANAGED兩種,一次只能配置一個,后面會介紹;
4⃣️dataSource-type:該屬性用來配置數據源類型,有UNPOOLED、POOLED和JNDI三種選擇,后面會介紹;
5⃣️dataSource中的property元素就是數據庫相關的信息
注意:environment可以配置多個,但是如果同一種模式,如development模式,配置了兩個環境environment,mybatis會用后面的覆蓋前面的,如下配置:
1 <environments default="development"> 2 <!--環境變量 --> 3 <environment id="development"> 4 <!--事務管理器 --> 5 <transactionManager type="MANAGED" /> 6 <!--數據源 --> 7 <dataSource type="POOLED"> 8 <property name="driver" value="${db.driver}" /> 9 <property name="url" value="${db.url}" /> 10 <property name="username" value="${db.username}" /> 11 <property name="password" value="${db.pwd}" /> 12 </dataSource> 13 </environment> 14 <!--環境變量 --> 15 <environment id="development"> 16 <!--事務管理器 --> 17 <transactionManager type="JDBC" /> 18 <!--數據源 --> 19 <dataSource type="POOLED"> 20 <property name="driver" value="${db.driver}" /> 21 <property name="url" value="${db.url}" /> 22 <property name="username" value="${db.username}" /> 23 <property name="password" value="${db.pwd}" /> 24 </dataSource> 25 </environment> 26 </environments>
上面的例子中我配了兩個environment,但是它們的環境模式都是開發模式,此時在開發環境中生效的是后面的,即事務管理器為JDBC的配置,所以一般多個最多配置兩個環境,且開發模式不同,一個是開發環境,一個是工作環境。下面通過代碼獲取環境配置信息:
1 /** 2 * 獲取環境信息 3 */ 4 public static void getEnvironment() { 5 SqlSession sqlSession = getSqlSession(); 6 Environment env = sqlSession.getConfiguration().getEnvironment(); 7 TransactionFactory tf = env.getTransactionFactory(); 8 System.out.println(tf.getClass().getSimpleName()); 9 }
輸出結果:
1 JdbcTransactionFactory
可以看到返回的事務管理器類型為JdbcTransactionFactory,而當我在配置中把事務管理器改成MANAGED時,會獲取到ManagedTransactionFactory類型。下面分開介紹事務管理器和數據源的配置內容。
二、transactionManager事務管理器配置
在MyBatis中,transactionManager提供了兩個實現類,都需要實現接口Transaction,我們可以查看以下它的源代碼:
1 public interface Transaction { 2 3 4 Connection getConnection() throws SQLException; 5 6 void commit() throws SQLException; 7 8 void rollback() throws SQLException; 9 10 void close() throws SQLException; 11 12 Integer getTimeout() throws SQLException; 13 14 }
從提供的方法中可以知道,它主要完成提交、回滾、關閉數據庫的事務。MyBatis中為Transaction接口提供了兩個實現類,分別是JdbcTransaction和ManagedTransaction,並且分別對應着JdbcTransactionFactory和ManagedTransactionFactory兩個工廠,這兩個工廠實現了TransactionFactory這個接口,當我們在配置文件中通過transactionManager的type屬性配置事務管理器類型的時候,mybatis就會自動從對應的工廠獲取實例。下面說一下這兩者的區別:
1⃣️JDBC使用JdbcTransactionFactory工廠生成的JdbcTransaction對象實現,以JDBC的方式進行數據庫的提交、回滾等操作;
2⃣️MANAGED使用ManagedTransactionFactory工廠生成的ManagedTransaction對象實現,它的提交和回滾不需要任何操作,而是把事務交給容器進行處理,默認情況下會關閉連接,如果不希望默認關閉,只要將其中的closeConnection屬性設置為false即可。
我在測試的過程中發現的最明顯的區別就是,如果我使用JDBC的事務處理方式,當我向數據庫中插入一條數據時,在調用完插入接口執行SQL之后,必須 執行sqlSession.commit();進行提交,否則雖然插入成功但是數據庫中還是看不到剛才插入的數據;而使用MANAGED方式就不一樣了,只需調用接口即可,無需手動提交。
當然,除了使用默認的,我們還可以根據需要自定義一個事務管理器,需要以下三步:
第一步:創建一個事務管理類,繼承ManagedTransaction或JdbcTransaction類或實現Transaction接口;
1 /** 2 * 定義自己的事務管理器 3 */ 4 public class MyTransaction extends JdbcTransaction implements Transaction { 5 6 // 重寫父類方法 7 public MyTransaction(Connection connection) { 8 super(connection); 9 } 10 11 public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { 12 super(ds, desiredLevel, desiredAutoCommit); 13 } 14 }
第二步:創建一個事務管理工廠類,實現TransactionFactory接口,提供生產事務處理相關接口;
1 /** 2 * 定義自己的事務管理器,實現獲取連接、提交、回滾、關閉數據庫連接等操作 3 */ 4 public class MyTransaction extends JdbcTransaction implements Transaction { 5 6 public MyTransaction(Connection connection) { 7 super(connection); 8 } 9 10 public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { 11 super(ds, desiredLevel, desiredAutoCommit); 12 } 13 14 @Override 15 public Connection getConnection() throws SQLException { 16 return super.getConnection(); 17 } 18 19 @Override 20 public void commit() throws SQLException { 21 super.commit(); 22 } 23 24 @Override 25 public void rollback() throws SQLException { 26 super.rollback(); 27 } 28 29 @Override 30 public void close() throws SQLException { 31 super.close(); 32 } 33 34 @Override 35 public Integer getTimeout() throws SQLException { 36 return super.getTimeout(); 37 } 38 }
第三步:配置自定義事務管理器
1 <transactionManager type="com.daily.objectfactory.MyTransactionFactory" />
注意⚠️:這個地方配置的是自定義的工廠類,而不是事務管理類,因為mybatis是根據配置的工廠獲取具體實例對象的。
要不是親手實踐,差點就忽略了這點呢!!!
通過以上三步就完成了自定義事務管理器的配置,其實我們還可以在別名設置這個工廠的別名,然后在此處引用,如下:
先在別名中配置工廠所在的包
1 <typeAliases> 2 <!-- 對包進行掃描,可以批量進行別名設置,設置規則是:獲取類名稱,將其第一個字母變為小寫 --> 3 <package name="com.daily.objectfactory" /> 4 </typeAliases>
然后按照規則,該包下所有類的別名是將類的第一個字母變成小寫,所以我自定義的這個事務管理器工廠MyTransactionFactory的別名就是myTransactionFactory,這樣我就可以在事務管理配置中使用該別名了,如下:
1 <!--事務管理器 --> 2 <transactionManager type="myTransactionFactory" />
三、dataSource數據源配置
在mybatis中,數據庫是通過PooledDataSourceFactory、UnpooledDataSourceFactory和JndiDataSourceFactory三個工廠類來提供,前兩者分別產生PooledDataSource和UnpooledDataSource類對象,第三個則會根據JNDI的信息拿到外部容器實現的數據庫連接對象,但是不管怎樣,它們最后都會生成一個實現了DataSource接口的數據庫連接對象。
它們的配置信息如下:
1 <dataSource type="POOLED"> 2 <dataSource type="UNPOOLED"> 3 <dataSource type="JNDI">
這三種數據源的意義如下:
1⃣️UNPOOLED
采用非數據庫池的管理方式,每次請求都會新建一個連接,所以性能不是很高,使用這種數據源的時候,我們可以配置以下屬性:
driver數據庫驅動名
url數據庫連接URL
username用戶名
password密碼
defaultTransactionIsolationLevel默認的事務隔離級別,如果要傳遞屬性給驅動,則屬性的前綴為driver
2⃣️POOLED
采用連接池的概念將數據庫鏈接對象Connection組織起來,可以在初始化時創建多個連接,使用時直接從連接池獲取,避免了重復創建連接所需的初始化和認證時間,從而提升了效率,所以這種方式比較適合對性能要求高的應用中。除了UNPOOLED中的配置屬性之外,還有下面幾個針對池子的配置:
poolMaximumActiveConnections:任意時間都會存在的連接數,默認值為10
poolMaxmumIdleConnections:可以空閑存在的連接數
poolMaxmumCheckoutTime:在被強制返回之前,檢查出存在空閑連接的等待時間。即如果有20個連接,只有一個空閑,在這個空閑連接被找到之前的等待時間就用這個屬性配置。
poolTimeToWait:等待一個數據庫連接成功所需的時間,如果超出這個時間則嘗試重新連接。
還有其他的一些配置,不詳述了。
3⃣️JNDI
數據源JNDI的實現是為了能在如EJB或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然后放置一個JNDI上下文的引用。這種數據源只需配置兩個屬性:
initial_context:用來在InitialContext中尋找上下文。可選,如果忽略,data_source屬性將會直接從InitialContext中尋找;
data_source:引用數據源實例位置上下文的路徑。當提供initial_context配置時,data_source會在其返回的上下文進行查找,否則直接從InitialContext中查找。
除了上述三種數據源之外,mybatis還提供第三方數據源,如DBCP,但是需要我們自定義數據源工廠並進行配置,這一點暫時不做研究。
以上就是environments運行環境的配置。