mybatis全配置理解

本文只論mybatis自己,不涉及與spring整合,文中探討了mybatis最新版本提供的所有配置項的做用。html

首先要了解都有哪些配置項,mybatis的SqlSession來自SqlSessionFactory,SqlSessionFactory來自SqlSessionFactoryBuilder,從SqlSessionFactoryBuilder切入分析java

...
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,而後看XMLConfigBuildermysql

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節點爲根節點。git

能夠配置10個子節點:properties、settings、typeAliases、plugins、objectFactory、objectWrapperFactory、environments、databaseIdProvider、typeHandlers、mappers。github

properties

這些屬性都是可外部配置且可動態替換的,既能夠在典型的 Java 屬性文件中配置,亦可經過 properties 元素的子元素來傳遞。例如:spring

<!-- 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 的運行時行爲。sql

<!-- 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。apache

參數介紹

參數json

官方中文描述

理解

可選值

默認值

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: 輸出提醒日誌 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'的日誌等級必須設置爲 WARN)

  • FAILING: 映射失敗 (拋出 SqlSessionException)

能夠不設置

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中.
因而對Map遍歷時,key就遍歷不到。部分狀況會有須要key存在,value=null的狀況,依據多數實際場景來看,使用默認值false沒問題。

能夠不設置

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>
相關文章
相關標籤/搜索