一、什麼是配置之屬性優化 在解答這個問題之前我們應該先明白MyBatis的配置有哪些? 官方文檔中文網:配置_MyBatis中文網。 我們還是直接看官方文檔中給出的內容: MyBatis 的配置文件包含了會深深影響 MyBatis 行為的設置和屬性信息。 配置文檔的頂層結構如下: configura ...
一、什麼是配置之屬性優化
在解答這個問題之前我們應該先明白MyBatis的配置有哪些?
官方文檔中文網:配置_MyBatis中文網。
我們還是直接看官方文檔中給出的內容:
MyBatis 的配置文件包含了會深深影響 MyBatis 行為的設置和屬性信息。 配置文檔的頂層結構如下:
configuration(配置)
properties(屬性)
settings(設置)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境配置)
environment(環境變數)
transactionManager(事務管理器)
dataSource(數據源)
databaseIdProvider(資料庫廠商標識)
mappers(映射器)
ok,看到上面的配置結構,我們會發現有一些是我們接觸過的,沒錯,就是environments(環境配置)和mappers(映射器)。我們在建立第一個MyBatis程式的時候,就在mybatis-config.xml配置文件中對它們進行了配置,當時他們是這樣的:
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/jms/dao/UserMapper.xml"/> </mappers> </configuration>
既然如此,我們在對屬性進行優化之前,先瞭解environments(環境配置)的一些內容。
環境配置(environments)
MyBatis 可以配置成適應多種環境,這種機制有助於將 SQL 映射應用於多種資料庫之中, 現實情況下有多種理由需要這麼做。例如,開發、測試和生產環境需要有不同的配置;或者想在具有相同 Schema 的多個生產資料庫中使用相同的 SQL 映射。還有許多類似的使用場景。
不過要記住:儘管可以配置多個環境,但每個 SqlSessionFactory 實例只能選擇一種環境。
這是官方文檔的內容,其中說可以配置多種環境,也就是說<environment id="development">...</environment>可以有多個,我們通過default="..."選擇其中一個,就像下麵的例子:
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> <environment id="test"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/jms/dao/UserMapper.xml"/> </mappers> </configuration>
這裡我配置了兩個環境,一個id為development,還有一個id為test,但是由於default="development",所以我選擇的是id為development的環境。
OK,明白了default和id所代表的含義,我們接下來看<transactionManager type="JDBC"/>事務管理器,還是先看官方給出的文檔:
事務管理器(transactionManager)
在 MyBatis 中有兩種類型的事務管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域。
MANAGED – 這個配置幾乎沒做什麼。它從不提交或回滾一個連接,而是讓容器來管理事務的整個生命周期(比如 JEE 應用伺服器的上下文)。 預設情況下它會關閉連接。然而一些容器並不希望連接被關閉,因此需要將 closeConnection 屬性設置為 false 來阻止預設的關閉行為。
提示:如果你正在使用 Spring + MyBatis,則沒有必要配置事務管理器,因為 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
所以說,事務管理器其實有JDBC和MANAGED兩種,但是我們一般都會選擇JDBC。
<dataSource type="POOLED">數據源:
數據源(dataSource)
dataSource 元素使用標準的 JDBC 數據源介面來配置 JDBC 連接對象的資源。
大多數 MyBatis 應用程式會按示例中的例子來配置數據源。雖然數據源配置是可選的,但如果要啟用延遲載入特性,就必須配置數據源。
有三種內建的數據源類型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
UNPOOLED– 這個數據源的實現會每次請求時打開和關閉連接。雖然有點慢,但對那些資料庫連接可用性要求不高的簡單應用程式來說,是一個很好的選擇。 性能表現則依賴於使用的資料庫,對某些資料庫來說,使用連接池並不重要,這個配置就很適合這種情形。UNPOOLED 類型的數據源僅僅需要配置以下 5 種屬性:
driver – 這是 JDBC 驅動的 Java 類全限定名(並不是 JDBC 驅動中可能包含的數據源類)。
url – 這是資料庫的 JDBC URL 地址。
username – 登錄資料庫的用戶名。
password – 登錄資料庫的密碼。
defaultTransactionIsolationLevel – 預設的連接事務隔離級別。
defaultNetworkTimeout – 等待資料庫操作完成的預設網路超時時間(單位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文檔以獲取更多信息。
作為可選項,你也可以傳遞屬性給資料庫驅動。只需在屬性名加上“driver.”首碼即可,例如:
driver.encoding=UTF8
這將通過 DriverManager.getConnection(url, driverProperties) 方法傳遞值為 UTF8 的 encoding 屬性給資料庫驅動。
POOLED– 這種數據源的實現利用“池”的概念將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間。 這種處理方式很流行,能使併發 Web 應用快速響應請求。
除了上述提到 UNPOOLED 下的屬性外,還有更多屬性用來配置 POOLED 的數據源:
poolMaximumActiveConnections – 在任意時間可存在的活動(正在使用)連接數量,預設值:10
poolMaximumIdleConnections – 任意時間可能存在的空閑連接數。
poolMaximumCheckoutTime – 在被強制返回之前,池中連接被檢出(checked out)時間,預設值:20000 毫秒(即 20 秒)
poolTimeToWait – 這是一個底層設置,如果獲取連接花費了相當長的時間,連接池會列印狀態日誌並重新嘗試獲取一個連接(避免在誤配置的情況下一直失敗且不列印日誌),預設值:20000 毫秒(即 20 秒)。
poolMaximumLocalBadConnectionTolerance – 這是一個關於壞連接容忍度的底層設置, 作用於每一個嘗試從緩存池獲取連接的線程。 如果這個線程獲取到的是一個壞的連接,那麼這個數據源允許這個線程嘗試重新獲取一個新的連接,但是這個重新嘗試的次數不應該超過 poolMaximumIdleConnections 與 poolMaximumLocalBadConnectionTolerance 之和。 預設值:3(新增於 3.4.5)
poolPingQuery – 發送到資料庫的偵測查詢,用來檢驗連接是否正常工作並準備接受請求。預設是“NO PING QUERY SET”,這會導致多數資料庫驅動出錯時返回恰當的錯誤消息。
poolPingEnabled – 是否啟用偵測查詢。若開啟,需要設置 poolPingQuery 屬性為一個可執行的 SQL 語句(最好是一個速度非常快的 SQL 語句),預設值:false。
poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的頻率。可以被設置為和資料庫連接超時時間一樣,來避免不必要的偵測,預設值:0(即所有連接每一時刻都被偵測 — 當然僅當 poolPingEnabled 為 true 時適用)。
JNDI – 這個數據源實現是為了能在如 EJB 或應用伺服器這類容器中使用,容器可以集中或在外部配置數據源,然後放置一個 JNDI 上下文的數據源引用。這種數據源配置只需要兩個屬性:
initial_context – 這個屬性用來在 InitialContext 中尋找上下文(即,initialContext.lookup(initial_context))。這是個可選屬性,如果忽略,那麼將會直接從 InitialContext 中尋找 data_source 屬性。
data_source – 這是引用數據源實例位置的上下文路徑。提供了 initial_context 配置時會在其返回的上下文中進行查找,沒有提供時則直接在 InitialContext 中查找。
和其他數據源配置類似,可以通過添加首碼“env.”直接把屬性傳遞給 InitialContext。比如:
env.encoding=UTF8
這就會在 InitialContext 實例化時往它的構造方法傳遞值為 UTF8 的 encoding 屬性。
看了以上文檔,我們主要要瞭解事務管理器的預設是JDBC,數據源預設的是POOLED。
接下來就只剩下環境配置中<property />標簽的內容了,很明顯,這就是屬性標簽,對於配置文件,官方給出的預設的格式是這樣的:
<property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/>
那麼我們怎麼樣才能和官方這種預設的格式匹配起來呢,現在我們就需要對屬性進行優化了。
屬性(properties)
這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性文件中配置這些屬性,也可以在 properties 元素的子元素中設置。
例如:
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
官方文檔中是這樣說明的,我們將屬性在外部配置或在properties的子元素中設置就是對屬性的優化。
二、怎麼進行屬性的優化
1.在java屬性文件中配置
(1)首先建立一個屬性文件db.properties,其中的內容如下:
diver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
(2)修改mybatis-config.xml配置文件
<?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="db.properties"> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <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> <mappers> <mapper resource="com/jms/dao/UserMapper.xml"/> </mappers> </configuration>
我們通過<properties resource="db.properties"> </properties>對db.properties文件進行了引用,在這種配置下我們去測試是完全可以的。
(2)直接在<properties>元素的子元素中進行設置
我現在先把db.properties文件中的username和password兩項刪掉,再去將<properties>元素內容修改為以下樣式:
<properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="123456"/> </properties>
此時我們去測試依舊沒有問題。
以上就是對屬性的優化,那麼問題來了,既可以直接在環境配置中賦值,又可以通過properties文件和<properties>元素的子元素堆屬性進行配置,當其中有重覆的屬性配置時,該使用哪一個配置呢?
官方在文檔中作出了以下規定:
如果一個屬性在不只一個地方進行了配置,那麼,MyBatis 將按照下麵的順序來載入:
首先讀取在 properties 元素體內指定的屬性。
然後根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件,或根據 url 屬性指定的路徑讀取屬性文件,並覆蓋之前讀取過的同名屬性。
最後讀取作為方法參數傳遞的屬性,並覆蓋之前讀取過的同名屬性。
因此,通過方法參數傳遞的屬性具有最高優先順序,resource/url 屬性中指定的配置文件次之,最低優先順序的則是 properties 元素中指定的屬性。
(本文僅作個人學習記錄用,如有紕漏敬請指正)