本文只論mybatis本身,不涉及與spring整合,文中探討了mybatis最新版本提供的全部配置項的作用。
首先要了解都有哪些配置項,mybatis的SqlSession來自SqlSessionFactory,SqlSessionFactory來自SqlSessionFactoryBuilder,從SqlSessionFactoryBuilder切入分析
... public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } ...
構造SqlSessionFactoryBuilder用到了XMLConfigBuilder,然后看XMLConfigBuilder
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; } private void parseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } } private void settingsElement(Properties props) throws Exception { configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL"))); configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE"))); configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory"))); configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false)); configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false)); configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true)); configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true)); configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false)); configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE"))); configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null)); configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false)); configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false)); configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION"))); configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER"))); configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString")); configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true)); configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage"))); @SuppressWarnings("unchecked") Class<? extends TypeHandler> typeHandler = (Class<? extends TypeHandler>)resolveClass(props.getProperty("defaultEnumTypeHandler")); configuration.setDefaultEnumTypeHandler(typeHandler); configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false)); configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true)); configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false)); configuration.setLogPrefix(props.getProperty("logPrefix")); @SuppressWarnings("unchecked") Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl")); configuration.setLogImpl(logImpl); configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory"))); }
configuration節點為根節點。
可以配置10個子節點:properties、settings、typeAliases、plugins、objectFactory、objectWrapperFactory、environments、databaseIdProvider、typeHandlers、mappers。
properties
這些屬性都是可外部配置且可動態替換的,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞。例如:
<!-- mybatis-config.xml --> <properties resource="jdbc.properties"></properties> <!-- mybatis-config.xml --> <properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/a"/> <property name="username" value="root"/> <property name="password" value="root"/> </properties>settings
settings
這是 MyBatis 中極為重要的調整設置,它們會改變 MyBatis 的運行時行為。
<!-- mybatis-config.xml --> <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>
懶加載
熟悉配置前需要知道什么是懶加載
public class Order { public Long id; public Long addressId; public Address address; }
public class Address { public Long id; public String name; }
<!-- addressMapper.xml --> <mapper namespace="addressMapperSpace"> <select id="getAddressById" parameterType="Long" resultType="Address"> select id,name from t_address where id = #{id} </select> </mapper>
<!-- orderMapper.xml --> <mapper namespace="..."> <resultMap id="orderMap" type="Order"> <id property="id" column="id" /> <association property="address" column="address_id" select="addressMapperSpace.getAddressById" /> </resultMap> <select id="getOrderById" resultMap="orderMap" parameterType="Long"> select id,address_id from t_order where id = #{id} <select> </mapper>
如果是懶加載,那么訪問order的address屬性時才會去查詢address。
參數介紹
參數 |
官方中文描述 |
理解 |
可選值 |
默認值 |
---|---|---|---|---|
cacheEnabled |
全局地開啟或關閉配置文件中的所有映射器已經配置的任何緩存。 |
mybatis二級緩存開關,不支持集群環境,設置成false防止意外。 |
true | false |
true |
lazyLoadingEnabled |
延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。 特定關聯關系中可通過設置fetchType屬性來覆蓋該項的開關狀態 |
可以不設置 |
true | false |
false |
aggressiveLazyLoading |
當開啟時,任何方法的調用都會加載該對象的所有屬性。否則,每個屬性會按需加載(參考lazyLoadTriggerMethods). |
當設置為true時,懶加載的對象可能被任何懶屬性全部加載;否則,每個屬性按需加載。一般不用。 可以不設置 |
true | false |
false (true in ≤3.4.1) |
lazyLoadTriggerMethods |
指定對象的哪個方法觸發一次延遲加載。 |
在lazyLoadingEnabled=true時有效,調用本方法會使得所有延遲加載屬性被加載,如果有多個懶加載屬性,可以使用這個方法把所有懶加載屬性一起加載了。 可以不設置 |
用逗號分隔的方法列表。 |
equals,clone,hashCode,toString |
proxyFactory |
指定 Mybatis 創建具有延遲加載能力的對象所用到的代理工具。 |
mybatis延遲加載用的工具,舊版本使用的是CGLIB動態代理技術,新版本支持使用JAVASSIST(Javassist是一個運行時編譯庫,他能動態的生成或修改類的字節碼)來完成。 可以不設置 |
CGLIB | JAVASSIST |
JAVASSIST (MyBatis 3.3 or above) |
multipleResultSetsEnabled |
是否允許單一語句返回多結果集(需要兼容驅動)。 |
sql與ResultSet一對多的用法, 沒找到用法。 可以不設置 |
true | false |
true |
useColumnLabel |
使用列標簽代替列名。不同的驅動在這方面會有不同的表現, 具體可參考相關驅動文檔或通過測試這兩種不同的模式來觀察所用驅動的結果。 |
在Select字段的時候使用AS,用得上,由於默認true。 可以不設置 |
true | false |
true |
useGeneratedKeys |
允許 JDBC 支持自動生成主鍵,需要驅動兼容。 如果設置為 true 則這個設置強制使用自動生成主鍵,盡管一些驅動不能兼容但仍可正常工作(比如 Derby)。 |
我們使用mysql數據庫自增主鍵,在xml的insert塊中如果使用useGeneratedKeys來獲得生成的主鍵,那這個屬性必須設置成true。如果使用以下方法,那也可以不設置。 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long"> SELECT LAST_INSERT_ID() </selectKey> |
true | false |
false |
autoMappingBehavior |
指定 MyBatis 應如何自動映射列到字段或屬性。 NONE 表示取消自動映射;PARTIAL 只會自動映射沒有定義嵌套結果集映射的結果集。 FULL 會自動映射任意復雜的結果集(無論是否嵌套)。 |
如果修改成FULL,會由於沒及時更新model導致映射失敗。 可以不設置 |
NONE, PARTIAL, FULL |
PARTIAL |
autoMappingUnknownColumnBehavior |
指定發現自動映射目標未知列(或者未知屬性類型)的行為。
|
可以不設置 |
NONE, WARNING, FAILING |
NONE |
defaultExecutorType |
配置默認的執行器。SIMPLE 就是普通的執行器;REUSE 執行器會重用預處理語句(prepared statements); BATCH 執行器將重用語句並執行批量更新。 |
1.設為"SIMPLE", 在執行dao.save()時,就相當於JDBC的stmt.execute(sql); 2.設為"REUSE", 在執行dao.save()時,相當於JDBC重用一條sql,再通過stmt傳入多項參數值,然后執行stmt.executeUpdate()或stmt.executeBatch();重用sql的場景不太常見,因此用SIMPLE就可以了。 3.設為"BATCH", 在執行dao.save()時,相當於JDBC語句的 stmt.addBatch(sql),即僅僅是將執行SQL加入到批量計划。 所以此時不會拋出主鍵沖突等運行時異常,而只有臨近commit前執行stmt.execteBatch()后才會拋出異常。 可以不設置 |
SIMPLE REUSE BATCH |
SIMPLE |
defaultStatementTimeout |
設置超時時間,它決定驅動等待數據庫響應的秒數。 |
這是以秒為單位的全局sql超時時間設置,當超出了設置的超時時間時,會拋出SQLTimeoutException。建議設置一個合理值。 |
任意正整數 |
Not Set (null) |
defaultFetchSize |
為驅動的結果集獲取數量(fetchSize)設置一個提示值。此參數只可以在查詢設置中被覆蓋。 |
mysql不支持fetchSize。 一般使用分頁插件即可。 可以不設置 |
任意正整數 |
Not Set (null) |
safeRowBoundsEnabled |
允許在嵌套語句中使用分頁(RowBounds)。如果允許使用則設置為false。 |
使用場景:session.select("...", null, new RowBounds(1, 2),resultHandler); 一般使用分頁插件即可。 可以不設置 |
true | false |
false |
safeResultHandlerEnabled |
允許在嵌套語句中使用分頁(ResultHandler)。如果允許使用則設置為false。 |
使用場景:session.select("...", null, new RowBounds(1, 2),resultHandler); 可以不設置 |
true | false |
true |
mapUnderscoreToCamelCase |
是否開啟自動駝峰命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的類似映射。 |
駝峰命名映射,手寫mapper不去寫resultMap時推薦開啟。使用mybatis-generator時,不開啟也ok。 |
true | false |
false |
localCacheScope |
MyBatis 利用本地緩存機制(Local Cache)防止循環引用(circular references)和加速重復嵌套查詢。 默認值為 SESSION,這種情況下會緩存一個會話中執行的所有查詢。 若設置值為 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不同調用將不會共享數據。 |
一級緩存在spring中基本也用不上,可以不設置 |
SESSION | STATEMENT |
SESSION |
jdbcTypeForNull |
當沒有為參數提供特定的 JDBC 類型時,為空值指定 JDBC 類型。 某些驅動需要指定列的 JDBC 類型,多數情況直接用一般類型即可,比如 NULL、VARCHAR 或 OTHER。 |
正常情況下我們都配了。 可以不設置 |
JdbcType 常量. 大多都為: NULL, VARCHAR and OTHER |
OTHER (java.lang.Object) |
defaultScriptingLanguage |
指定動態 SQL 生成的默認語言。 |
雖然官方名稱叫做LanguageDriver,其實叫做解析器可能更加合理。MyBatis 從 3.2 開始支持可插拔的腳本語言,因此你可以在插入一種語言的驅動(language driver)之后來寫基於這種語言的動態 SQL 查詢比如mybatis除了XML格式外,還提供了mybatis-velocity,允許使用velocity表達式編寫SQL語句。可以通過實現LanguageDriver接口的方式來插入一種語言。 可以不設置 |
一個類型別名或完全限定類名。 |
org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler |
指定 Enum 使用的默認 TypeHandler 。 (從3.4.5開始) |
默認的EnumTypeHandler存入數據庫的是枚舉的name, mybatis還提供了EnumOrdinalTypeHandler存入數據庫的是枚舉的位置。 這倆都不太好用,如果想要把數據庫查詢結果與枚舉自動轉換,可以自定義typeHandler來實現。在查詢或操作數據時以枚舉傳輸優勢並不大,只提供對應的枚舉也可滿足需求。 可以不設置 |
一個類型別名或完全限定類名。 |
org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls |
指定當結果集中值為 null 的時候是否調用映射對象的 setter(map 對象時為 put)方法,這對於有 Map.keySet() 依賴或 null 值初始化的時候是有用的。注意基本類型(int、boolean等)是不能設置成 null 的。 |
假設將數據從DB中查詢出來如果將字段映射為Map,而不想封裝成Bean。默認情況下,Mybatis對Map的解析生成, 如果值(value)為null的話,那么key也不會被加入到map中. 可以不設置 |
true | false |
false |
returnInstanceForEmptyRow |
當返回行的所有列都是空時,MyBatis默認返回null。 當開啟這個設置時,MyBatis會返回一個空實例。 請注意,它也適用於嵌套的結果集 (i.e. collectioin and association)。(從3.4.2開始) |
查詢結果沒有的時候,返回null是合理的,返回一個空對象容易引起誤會。 不要設置 |
true | false |
false |
logPrefix |
指定 MyBatis 增加到日志名稱的前綴。 |
日志前綴,要不要看個人喜好。 可以不設置 |
任何字符串 |
Not set |
logImpl |
指定 MyBatis 所用日志的具體實現,未指定時將自動查找。 |
不要設置 |
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING |
Not set |
vfsImpl |
指定VFS的實現 |
VFS主要用來加載容器內的各種資源,比如jar或者class文件。mybatis提供了2個實現 JBoss6VFS 和 DefaultVFS,並提供了用戶擴展點,用於自定義VFS實現,加載順序是自定義VFS實現 > 默認VFS實現 取第一個加載成功的,默認情況下會先加載JBoss6VFS,如果classpath下找不到jboss的vfs實現才會加載默認VFS實現。 |
自定義VFS的實現的類全限定名,以逗號分隔。 |
Not set |
useActualParamName |
允許使用方法簽名中的名稱作為語句參數名稱。 為了使用該特性,你的工程必須采用Java 8編譯,並且加上-parameters選項。(從3.4.1開始) |
mybatis的全局配置useActualParamName決定了mapper中參數的寫法,默認為true。此時無需再使用@Param。 Order getOrderByCondition (Long id,Long addressId) <select id="getOrderByCondition" resultType="Order" > select * from t_order where id = #{id} and addressId = #{addressId} </select> 如果是false那么可寫成 <select id="getOrderByCondition" resultType="Order" > select * from t_order where id = #{0} and addressId = #{1} </select> 使用這個特性必須在jdk1.8場景。這是因為:在Java 8之前的版本,代碼編譯為class文件后,方法參數的類型是固定的,但參數名稱卻丟失了,這和動態語言嚴重依賴參數名稱形成了鮮明對比。現在,Java 8開始在class文件中保留參數名,給反射帶來了極大的便利。jdk8增加了類Parameter。 可以不設置 |
true | false |
true |
configurationFactory |
指定一個提供Configuration實例的類。 這個被返回的Configuration實例用來加載被反序列化對象的懶加載屬性值。 這個類必須包含一個簽名方法static Configuration getConfiguration(). (從 3.2.3 版本開始) |
此時mybatis全局的Configuration將被開發者手動指定。 建議不設置 |
類型別名或者全類名. |
Not set |
typeAliases
類型別名是為 Java 類型設置一個短的名字。它只和 XML 配置有關,原理是用hashMap關聯,存在的意義僅在於用來減少類完全限定名的冗余。例如:
<!-- mybatis-config.xml --> <typeAliases> <typeAlias alias="OrderMain" type="order.center.domain.OrderMain"/> </typeAliases> <!-- mybatis-config.xml --> <typeAliases> <package name="order.center.domain"/> </typeAliases>
typeHandlers
無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。
可以重寫類型處理器或創建你自己的類型處理器來處理不支持的或非標准的類型。 具體做法為:實現 org.apache.ibatis.type.TypeHandler 接口, 或繼承一個很便利的類 org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個 JDBC 類型。
下面是一個處理javaType=com.alibaba.fastjson.JSON時的例子
public class ExampleTypeHandler extends BaseTypeHandler<JSON> { @Override public void setNonNullParameter(PreparedStatement ps, int i, JSON parameter, JdbcType jdbcType) throws SQLException { ps.setString(i,parameter.toJSONString()); } @Override public JSON getNullableResult(ResultSet rs, String columnName) throws SQLException { return JSON.parseObject(rs.getString(columnName)); } @Override public JSON getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return JSON.parseObject(rs.getString(columnIndex)); } @Override public JSON getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return JSON.parseObject(cs.getString(columnIndex)); } }
<!-- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>
<!-- Ordermapper.xml中使用 --> <result column="order_json" typeHandler="org.mybatis.example.ExampleTypeHandle" jdbcType="VARCHAR" property="orderJson" />
objectFactory
MyBatis 每次創建結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。 默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數映射存在的時候通過參數構造方法來實例化。 如果想覆蓋對象工廠的默認行為,則可以通過創建自己的對象工廠來實現。比如:
// 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="someProperty" value="100"/> </objectFactory>
一般情況很少會使用到自定義ObjectFactory,如果需要使用的話,建議是在對象創建時需要做一些操作,或前或后,用於改變或者豐富被創建對象。
objectWrapperFactory
最新的官方文檔中已經找不到這個配置項。原用來提供自定義的ObjectWrapper
plugins
MyBatis 允許你在已映射語句執行過程中的某一點進行攔截調用。默認情況下,MyBatis 允許使用插件來攔截的方法調用包括:
-
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
-
ParameterHandler (getParameterObject, setParameters)
-
ResultSetHandler (handleResultSets, handleOutputParameters)
-
StatementHandler (prepare, parameterize, batch, update, query)
這些類中方法的細節可以通過查看每個方法的簽名來發現,或者直接查看 MyBatis 發行包中的源代碼。 如果你想做的不僅僅是監控方法的調用,那么你最好相當了解要重寫的方法的行為。 因為如果在試圖修改或重寫已有方法的行為的時候,你很可能在破壞 MyBatis 的核心模塊。 這些都是更低層的類和方法,所以使用插件的時候要特別當心。
通過 MyBatis 提供的強大機制,使用插件是非常簡單的,只需實現 Interceptor 接口,並指定想要攔截的方法簽名即可。
例如配置pageHelper:
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="com.github.pagehelper.PageHelper"> <property name="dialect" value="mysql"/> <property name="offsetAsPageNum" value="false"/> <property name="rowBoundsWithCount" value="false"/> <property name="pageSizeZero" value="true"/> <property name="reasonable" value="false"/> <property name="supportMethodsArguments" value="false"/> <property name="returnPageInfo" value="none"/> </plugin> </plugins>
environments
MyBatis 可以配置成適應多種環境,這種機制有助於將 SQL 映射應用於多種數據庫之中, 現實情況下有多種理由需要這么做。例如,開發、測試和生產環境需要有不同的配置;或者共享相同 Schema 的多個生產數據庫, 想使用相同的 SQL 映射。許多類似的用例。
不過要記住:盡管可以配置多個環境,每個 SqlSessionFactory 實例只能選擇其一。
所以,如果你想連接兩個數據庫,就需要創建兩個 SqlSessionFactory 實例,每個數據庫對應一個。而如果是三個數據庫,就需要三個實例,依此類推,記起來很簡單:
-
每個數據庫對應一個 SqlSessionFactory 實例
為了指定創建哪種環境,只要將它作為可選的參數傳遞給 SqlSessionFactoryBuilder 即可。可以接受環境配置的兩個方法簽名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略了環境參數,那么默認環境將會被加載,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
環境元素定義了如何配置環境。
<!-- mybatis-config.xml --> <environments default="development"> <environment id="development"> <!--Mybatis管理事務是分為兩種方式: (1)使用JDBC的事務管理機制,就是利用java.sql.Connection對象完成對事務的提交 (2)使用MANAGED的事務管理機制,這種機制mybatis自身不會去實現事務管理,而是讓程序的容器(JBOSS,WebLogic)來實現對事務的管理 --> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!-- 可以直接用properties也可以在這配 --> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> <environment id="test"> <!-- mybatis提供的區分不同環境的數據庫連接配置 --> </environment> </environments>
databaseIdProvider
MyBatis 可以根據不同的數據庫廠商執行不同的語句,這種多廠商的支持是基於映射語句中的 databaseId 屬性。 MyBatis 會加載不帶 databaseId 屬性和帶有匹配當前數據庫 databaseId 屬性的所有語句。 如果同時找到帶有 databaseId 和不帶 databaseId 的相同語句,則后者會被舍棄。 為支持多廠商特性只要像下面這樣在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:
我們實際使用中,不同數據庫大概率是不同數據源,很低概率出現同一個mapper兩種數據庫使用,因此這個配置項幾乎不可能用上。
<!-- mybatis-config.xml --> <databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> <property name="Mysql" value="mysql" /> </databaseIdProvider>
<!-- mapper.xml --> <insert id="insertTest" ...> INSERT INTO users(name, age) VALUES('zhangsan', 1), ('wangwu', 2), ('zhaoliu', 3); </insert> <insert id="insertTest" ... databaseId="oracle"> INSERT ALL INTO users VALUES('zhangsan', 1) INTO users VALUES ('wangwu', 2) INTO users VALUES ('zhaoliu', 3); </insert>
mappers
既然 MyBatis 的行為已經由上述元素配置完了,我們現在就要定義 SQL 映射語句了。但是首先我們需要告訴 MyBatis 到哪里去找到這些語句。 Java 在自動查找這方面沒有提供一個很好的方法,所以最佳的方式是告訴 MyBatis 到哪里去找映射文件。你可以使用相對於類路徑的資源引用, 或完全限定資源定位符(包括 file:/// 的 URL),或類名和包名等。例如:
<!-- mybatis-config.xml 使用spring后可以在sqlSessionFactory里配置*.xml--> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
<!-- mybatis-config.xml 此方法mapper接口和xml必須同名放在一起--> <mappers> <package name="org.mybatis.builder"/> </mappers>
<!-- mybatis-config.xml 絕對路徑,不可用--> <mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers>