mybatis_user_guide(3)XML配置
【0】MyBatis 的配置文件包含了影響 MyBatis 行為甚深的設置(settings)和屬性(properties)信息。文檔的頂層結構如下: - configuration 配置- properties 屬性- settings 設置- typeAliases 類型命名- typeHandlers 類型處理器- objectFactory 對象工廠- plugins 插件- environments 環境- environment 環境變量- transactionManager 事務管理器- dataSource 數據源- databaseIdProvider 數據庫廠商標識- mappers 映射器【1】properties 屬性 method1)通過屬性文件引入屬性配置
method2)通過 <properties> 子元素 <property> 動態配置 <properties resource="jdbc.properties"><property name="username" value="error_root"/></properties>method3)通過 方法傳遞設置 SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props); // ... or ... SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);1)如果屬性在不只一個地方進行了配置,那么 MyBatis 將按照下面的順序來加載:(干貨——屬性設置的優先級) 1.1)在 properties 元素體內指定的屬性首先被讀取。 1.2)然后根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,并覆蓋已讀取的同名屬性。 1.3)最后讀取作為方法參數傳遞的屬性,并覆蓋已讀取的同名屬性。
因此,通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。
【2】setting 1)intro:?這是 MyBatis 中極為重要的調整設置,它們會改變 MyBatis 的運行時行為。 2)下表描述了設置中各項的意圖、默認值等: 3)一個配置完整的 settings 元素的示例如下: <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="autoMappingBehavior" value="PARTIAL"/><setting name="autoMappingUnknownColumnBehavior" value="WARNING"/><setting name="defaultExecutorType" value="SIMPLE"/><setting name="defaultStatementTimeout" value="25"/><setting name="defaultFetchSize" value="100"/><setting name="safeRowBoundsEnabled" value="false"/><setting name="mapUnderscoreToCamelCase" value="false"/><setting name="localCacheScope" value="SESSION"/><setting name="jdbcTypeForNull" value="OTHER"/><setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings> 【3】typeAliases 1)intro:類型別名是為 Java 類型設置一個短的名,就是取個別名; 2)取別名 <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的地方。3)也可以指定一個包名,MyBatis 會在包名下面搜索需要的 Java Bean <typeAliases><package name="domain.blog"/> </typeAliases> supplement)每一個在包?domain.blog?中的 Java Bean,在沒有注解的情況下,會使用 Bean 的首字母小寫的非限定類名來作為它的別名。 比如?domain.blog.Author?的別名為?author;若有注解,則別名為其注解值。看下面的例子:
4)已經為許多常見的 Java 類型內建了相應的類型別名。它們都是大小寫不敏感的,需要注意的是由基本類型名稱重復導致的特殊處理。
【4】類型處理器 1)intro:無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。下表描述了一些默認的類型處理器。
2)你可以重寫類型處理器或創建你自己的類型處理器來處理不支持的或非標準的類型。 具體做法為:實現?org.apache.ibatis.type.TypeHandler?接口, 或繼承一個很便利的類?org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個 JDBC 類型。比如: // ExampleTypeHandler.java @MappedJdbcTypes(JdbcType.VARCHAR) public class ExampleTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter);}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getString(columnName);}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getString(columnIndex);}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return cs.getString(columnIndex);} } <!-- mybatis-config.xml 在 mybatis的配置文件 xml 中 引用該類型處理器--> <typeHandlers><typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers> 3)?最后,可以讓 MyBatis 為你查找類型處理器: <!-- mybatis-config.xml --> <typeHandlers><package name="org.mybatis.example"/> </typeHandlers> Attention) 注意在使用自動檢索(autodiscovery)功能的時候,只能通過注解方式來指定 JDBC 的類型。
【5】處理枚舉類型(EnumTypeHandler?和?EnumOrdinalTypeHandler) 1)intro:若想映射枚舉類型?Enum,則需要從?EnumTypeHandler?或者?EnumOrdinalTypeHandler?中選一個來使用。 Attention)注意?EnumTypeHandler?在某種意義上來說是比較特別的,其他的處理器只針對某個特定的類,而它不同,它會處理任意繼承了?Enum?的類。
2)看個荔枝:比如說我們想存儲取近似值時用到的舍入模式。 2.1)默認情況下:MyBatis 會利用?EnumTypeHandler?來把?Enum?值轉換成對應的名字。 2.2)不過,我們可能不想存儲名字,相反我們的 DBA 會堅持使用整形值代碼:?在配置文件中把?EnumOrdinalTypeHandler?加到?typeHandlers?中即可, 這樣每個?RoundingMode?將通過他們的序數值來映射成對應的整形; <!-- mybatis-config.xml --> <typeHandlers><typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/> </typeHandlers>
2)problem+solution: 2.1)problem:但是怎樣能將同樣的?Enum?既映射成字符串又映射成整形呢?
2.2)solution:自動映射器(auto-mapper)會自動地選用?EnumOrdinalTypeHandler?來處理, 所以如果我們想用普通的?EnumTypeHandler,就非要為那些 SQL 語句顯式地設置要用到的類型處理器不可。
【6】objectFactory 對象工廠 1)intro:MyBatis 每次創建結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。 默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數映射存在的時候通過參數構造方法來實例化。? 2)自定義對象工廠:?如果想覆蓋對象工廠的默認行為,則可以通過創建自己的對象工廠來實現。比如: // 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);}public <T> boolean isCollection(Class<T> type) {return Collection.class.isAssignableFrom(type);}} <!-- mybatis-config.xml --> <objectFactory type="org.mybatis.example.ExampleObjectFactory"><property name="setProperties" value="100"/> </objectFactory> 對以上代碼的分析(Analysis):?ObjectFactory 接口很簡單,它包含兩個創建用的方法,一個是處理默認構造方法的,另外一個是處理帶參數的構造方法的。 最后,setProperties 方法可以被用來配置 ObjectFactory,在初始化你的 ObjectFactory 實例后, objectFactory 元素體中定義的屬性會被傳遞給 setProperties 方法。
【7】?plugins 插件 1)intro:?MyBatis 允許你在已映射語句執行過程中的某一點進行攔截調用。 2)默認情況下,MyBatis 允許使用插件來攔截的方法調用包括:? ?? - Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)- ParameterHandler (getParameterObject, setParameters)- ResultSetHandler (handleResultSets, handleOutputParameters)- StatementHandler (prepare, parameterize, batch, update, query) Attention)?因為如果在試圖修改或重寫已有方法的行為的時候,你很可能在破壞 MyBatis 的核心模塊。 這些都是更低層的類和方法,所以使用插件的時候要特別當心。(干貨——使用插件的時候要特別當心)
2)如何使用插件?只需實現 Interceptor 接口,并指定了想要攔截的方法簽名即可。 // 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) {} } <!-- mybatis-config.xml --> <plugins><plugin interceptor="org.mybatis.example.ExamplePlugin"><property name="setProperties" value="100"/></plugin> </plugins> 對以上代碼的分析(Analysis):?上面的插件將會攔截在 Executor 實例中所有的 “update” 方法調用, 這里的 Executor 是負責執行低層映射語句的內部對象。
Attention)除了用插件來修改 MyBatis 核心行為之外,還可以通過完全覆蓋配置類來達到目的。只需繼承后覆蓋其中的每個方法,再把它傳遞到 sqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,這可能會嚴重影響 MyBatis 的行為,務請慎之又慎。(干貨——再次重申,這可能會嚴重影響 MyBatis 的行為,務請慎之又慎)
【7】environments ?環境 1)可以配置多個環境,每個 SqlSessionFactory 實例只能選擇其一。?所以,如果你想連接兩個數據庫,就需要創建兩個 SqlSessionFactory 實例,每個數據庫對應一個。而如果是三個數據庫,就需要三個實例,依此類推,記起來很簡單; 2)每個數據庫對應一個 SqlSessionFactory 實例:?為了指定創建哪種環境,只要將它作為可選的參數傳遞給 SqlSessionFactoryBuilder 即可。可以接受環境配置的兩個方法簽名是: SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment); SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties); 2.1)?如果忽略了環境參數,那么默認環境將會被加載,如下所示: SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader); SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties); 2.2)環境元素定義了如何配置環境。 <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>
注意這里的關鍵點:
默認的環境 ID(比如:default=”development”)。 每個 environment 元素定義的環境 ID(比如:id=”development”)。 事務管理器的配置(比如:type=”JDBC”)。 數據源的配置(比如:type=”POOLED”)。 保證默認環境要匹配其中一個環境ID。(干貨——即是說,必要要配置默認環境==development)【7.1】transactionManager 事務管理器 1)intro:?在 MyBatis 中有兩種類型的事務管理器(也就是 type=”[JDBC|MANAGED]”): type1)JDBC :?這個配置就是直接使用了 JDBC 的提交和回滾設置,它依賴于從數據源得到的連接來管理事務范圍。(干貨——可以直接使用回滾和提交的設置) type2)MANAGED:?這個配置幾乎沒做什么。它從來不提交或回滾一個連接,而是讓容器來管理事務的整個生命周期(比如 JEE 應用服務器的上下文)。 默認情況下它會關閉連接,然而一些容器并不希望這樣,因此需要將 closeConnection 屬性設置為 false 來阻止它默認的關閉行為。例如: <transactionManager type="MANAGED"><property name="closeConnection" value="false"/> </transactionManager> Attention)?如果你正在使用 Spring + MyBatis,則沒有必要配置事務管理器, 因為 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
2)這兩種事務管理器類型都不需要任何屬性。它們不過是類型別名,換句話說,你可以使用 TransactionFactory 接口的實現類的完全限定名或類型別名代替它們。
public interface TransactionFactory {void setProperties(Properties props); Transaction newTransaction(Connection conn);Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit); }
3)任何在 XML 中配置的屬性在實例化之后將會被傳遞給 setProperties() 方法。你也需要創建一個 Transaction 接口的實現類,這個接口也很簡單: public interface Transaction {Connection getConnection() throws SQLException;void commit() throws SQLException;void rollback() throws SQLException;void close() throws SQLException;Integer getTimeout() throws SQLException; } Attention)使用這兩個接口,你可以完全自定義 MyBatis 對事務的處理。(干貨——通過實現 TransactionFactory 和 Transaction 接口 可以自定義 MyBatis 對事務的處理,即設置回滾和是否自動提交)
【7.2】dataSource 數據源
1)intro:?有三種內建的數據源類型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):
【7.2.1】UNPOOL 類型的數據源 1)intro:?這個數據源的實現只是每次被請求時打開和關閉連接; 2)UNPOOLED 類型的數據源僅僅需要配置以下 5 種屬性: property1)driver:?這是 JDBC 驅動的 Java 類的完全限定名(并不是JDBC驅動中可能包含的數據源類)。 property2)url:這是數據庫的 JDBC URL 地址。 property3)username:登錄數據庫的用戶名。 property4)password:登錄數據庫的密碼。 property5)defaultTransactionIsolationLevel:默認的連接事務隔離級別。
Supplement)作為可選項,你也可以傳遞屬性給數據庫驅動。要這樣做,屬性的前綴為“driver.”,例如:driver.encoding=UTF8;這將通過DriverManager.getConnection(url,driverProperties)方法傳遞值為?UTF8?的?encoding?屬性給數據庫驅動。
【7.2.2】POOLED類型的數據源 1)intro:?這種數據源的實現利用“池”的概念將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間。 這是一種使得并發 Web 應用快速響應請求的流行處理方式。? 2)除了上述提到 UNPOOLED 下的屬性外,會有更多屬性用來配置 POOLED 的數據源: - poolMaximumActiveConnections – 在任意時間可以存在的活動(也就是正在使用)連接數量,默認值:10- poolMaximumIdleConnections – 任意時間可能存在的空閑連接數。- poolMaximumCheckoutTime – 在被強制返回之前,池中連接被檢出(checked out)時間,默認值:20000 毫秒(即 20 秒)- poolTimeToWait – 這是一個底層設置,如果獲取連接花費的相當長的時間,它會給連接池打印狀態日志并重新嘗試獲取一個連接(避免在誤配置的情況下一直安靜的失敗),默認值:20000 毫秒(即 20 秒)。- poolPingQuery – 發送到數據庫的偵測查詢,用來檢驗連接是否處在正常工作秩序中并準備接受請求。默認是“NO PING QUERY SET”,這會導致多數數據庫驅動失敗時帶有一個恰當的錯誤消息。- poolPingEnabled – 是否啟用偵測查詢。若開啟,也必須使用一個可執行的 SQL 語句設置 poolPingQuery 屬性(最好是一個非常快的 SQL),默認值:false。- poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的使用頻度。這可以被設置成匹配具體的數據庫連接超時時間,來避免不必要的偵測,默認值:0(即所有連接每一時刻都被偵測 — 當然僅當 poolPingEnabled 為 true 時適用)。
【7.2.3】JNDI類型的數據源: 1)intro:?這個數據源的實現是為了能在如 EJB 或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然后放置一個 JNDI 上下文的引用; 2)這種數據源配置只需要兩個屬性:
- initial_context – 這個屬性用來在 InitialContext 中尋找上下文(即,initialContext.lookup(initial_context))。這是個可選屬性,如果忽略,那么 data_source 屬性將會直接從 InitialContext 中尋找。- data_source – 這是引用數據源實例位置的上下文的路徑。提供了 initial_context 配置時會在其返回的上下文中進行查找,沒有提供時則直接在 InitialContext 中查找。 3)和其他數據源配置類似,可以通過添加前綴“env.”直接把屬性傳遞給初始上下文。比如:?env.encoding=UTF8 ,這就會在初始上下文(InitialContext)實例化時往它的構造方法傳遞值為?UTF8?的?encoding?屬性;
4)通過需要實現接口?org.apache.ibatis.datasource.DataSourceFactory?, 也可使用任何第三方數據源,:
public interface DataSourceFactory {void setProperties(Properties props);DataSource getDataSource(); }5) org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory?可被用作父類來構建新的數據源適配器,比如下面這段插入 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();} }6) 為了令其工作,為每個需要 MyBatis 調用的 setter 方法中增加一個屬性。下面是一個可以連接至 PostgreSQL 數據庫的例子:
<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>【8】?databaseIdProvider 數據庫廠商標識 1)intro:?MyBatis 可以根據不同的數據庫廠商執行不同的語句,這種多廠商的支持是基于映射語句中的?databaseId?屬性。 MyBatis 會加載不帶?databaseId?屬性和帶有匹配當前數據庫?databaseId?屬性的所有語句。 如果同時找到帶有?databaseId?和不帶?databaseId?的相同語句,則后者會被舍棄。? 2)為支持多廠商特性只要像下面這樣在 mybatis-config.xml 文件中加入?databaseIdProvider?即可: <databaseIdProvider type="DB_VENDOR" /> 3)這里的 DB_VENDOR 會通過?DatabaseMetaData#getDatabaseProductName() ?返回的字符串進行設置。?由于通常情況下這個字符串都非常長而且相同產品的不同版本會返回不同的值,所以最好通過設置屬性別名來使其變短,如下: <databaseIdProvider type="DB_VENDOR"><property name="SQL Server" value="sqlserver"/><property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> </databaseIdProvider>
【9】?mappers 映射器 1)intro:?既然 MyBatis 的行為已經由上述元素配置完了,我們現在就要定義 SQL 映射語句了。?你可以使用相對于類路徑的資源引用, 或完全限定資源定位符(包括?file:///?的 URL),或類名和包名等。例如: <!-- Using classpath relative resources --> <mappers><mapper resource="org/mybatis/builder/AuthorMapper.xml"/><mapper resource="org/mybatis/builder/BlogMapper.xml"/><mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers> <!-- Using url fully qualified paths --> <mappers><mapper url="file:///var/mappers/AuthorMapper.xml"/><mapper url="file:///var/mappers/BlogMapper.xml"/><mapper url="file:///var/mappers/PostMapper.xml"/> </mappers> <!-- Using mapper interface classes --> <mappers><mapper class="org.mybatis.builder.AuthorMapper"/><mapper class="org.mybatis.builder.BlogMapper"/><mapper class="org.mybatis.builder.PostMapper"/> </mappers> <!-- Register all interfaces in a package as mappers --> <mappers><package name="org.mybatis.builder"/> </mappers>
Attention)這些配置會告訴了 MyBatis 去哪里找映射文件,剩下的細節就應該是每個 SQL 映射文件了,也就是接下來我們要討論的。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的mybatis_user_guide(3)XML配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果原装耳机如何真假辨别
- 下一篇: 手机软件闪退怎么办