Mybatis基礎(chǔ)知識1-XML配置

參考w3c 教程

1.概述

  • MyBatis 是支持定制化SQL、存儲過程以及高級映射的優(yōu)秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以對配置和原生Map使用簡單的 XML 或注解,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數(shù)據(jù)庫中的記錄。

  • 安裝
    使用 Maven 來構(gòu)建項目,則需將下面的 dependency 代碼置于 pom.xml 文件中:

<dependency>  
    <groupId>org.mybatis</groupId>  
    <artifactId>mybatis</artifactId>  
    <version>x.x.x</version>
</dependency>
  • 功能架構(gòu)
    1)API接口層:提供給外部使用的接口API,開發(fā)人員通過這些本地API來操縱數(shù)據(jù)庫。接口層一接收到調(diào)用請求就會調(diào)用數(shù)據(jù)處理層來完成具體的數(shù)據(jù)處理。
    2)數(shù)據(jù)處理層:負(fù)責(zé)具體的SQL查找、SQL解析、SQL執(zhí)行和執(zhí)行結(jié)果映射處理等。它主要的目的是根據(jù)調(diào)用的請求完成一次數(shù)據(jù)庫操作。
    3)基礎(chǔ)支撐層:負(fù)責(zé)最基礎(chǔ)的功能支撐,包括連接管理、事務(wù)管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來作為最基礎(chǔ)的組件。為上層的數(shù)據(jù)處理層提供最基礎(chǔ)的支撐。

  • 優(yōu)點
    1)簡單易學(xué):本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar文件+配置幾個sql映射文件易于學(xué)習(xí),易于使用,通過文檔和源代碼,可以比較完全的掌握它的設(shè)計思路和實現(xiàn)。
    2)靈活:mybatis不會對應(yīng)用程序或者數(shù)據(jù)庫的現(xiàn)有設(shè)計強加任何影響。 sql寫在xml里,便于統(tǒng)一管理和優(yōu)化。通過sql基本上可以實現(xiàn)我們不使用數(shù)據(jù)訪問框架可以實現(xiàn)的所有功能,或許更多。
    3)解除sql與程序代碼的耦合:通過提供DAL層,將業(yè)務(wù)邏輯和數(shù)據(jù)訪問邏輯分離,使系統(tǒng)的設(shè)計更清晰,更易維護,更易單元測試。sql和代碼的分離,提高了可維護性。
    4)提供映射標(biāo)簽,支持對象與數(shù)據(jù)庫的orm字段關(guān)系映射
    5)提供對象關(guān)系映射標(biāo)簽,支持對象關(guān)系組建維護
    6)提供xml標(biāo)簽,支持編寫動態(tài)sql。

  • 缺點
    1)編寫SQL語句時工作量很大,尤其是字段多、關(guān)聯(lián)表多時,更是如此。
    2)SQL語句依賴于數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫移植性差,不能更換數(shù)據(jù)庫。
    3)框架還是比較簡陋,功能尚有缺失,雖然簡化了數(shù)據(jù)綁定代碼,但是整個底層數(shù)據(jù)庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應(yīng)快速數(shù)據(jù)庫修改。
    4)二級緩存機制不佳

2.XML配置

  • 包含設(shè)置信息(settings)和屬性信息(properties)

2.1 properties

  • 這些屬性都是可外部配置且可動態(tài)替換的,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞。例如:
<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

其中的屬性就可以在整個配置文件中使用來替換需要動態(tài)配置的屬性值。比如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

這個例子中的 username 和 password 將會由 properties 元素中設(shè)置的相應(yīng)值來替換。 driver 和 url 屬性將會由 config.properties 文件中對應(yīng)的值來替換。這樣就為配置提供了諸多靈活選擇。
屬性也可以被傳遞到 SqlSessionBuilder.build()方法中。例如:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);

    // ... or ...

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);

如果屬性在不只一個地方進行了配置,那么 MyBatis 將按照下面的順序來加載:
1)在 properties 元素體內(nèi)指定的屬性首先被讀取。
2)然后根據(jù) properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據(jù) url 屬性指定的路徑讀取屬性文件,并覆蓋已讀取的同名屬性。
3)最后讀取作為方法參數(shù)傳遞的屬性,并覆蓋已讀取的同名屬性。
因此,通過方法參數(shù)傳遞的屬性具有最高優(yōu)先級,resource/url 屬性中指定的配置文件次之,最低優(yōu)先級的是 properties 屬性中指定的屬性

2.2 settings

  • 會改變 MyBatis 的運行時行為





<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="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <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>

2.3 typeAliases

  • 類型別名是為 Java 類型設(shè)置一個短的名字。它只和 XML 配置有關(guān),存在的意義僅在于用來減少類完全限定名的冗余。例如:
<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>

當(dāng)這樣配置時,Blog可以用在任何使用domain.blog.Blog的地方。
也可以指定一個包名,MyBatis 會在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

每一個在包 domain.blog 中的 Java Bean,在沒有注解的情況下,會使用 Bean 的首字母小寫的非限定類名來作為它的別名。 比如 domain.blog.Author 的別名為 author;若有注解,則別名為其注解值??聪旅娴睦樱?/p>

    @Alias("author")
    public class Author {
        ...
    }

已經(jīng)為許多常見的 Java 類型內(nèi)建了相應(yīng)的類型別名。它們都是大小寫不敏感的,需要注意的是由基本類型名稱重復(fù)導(dǎo)致的特殊處理。



2.4 typeHandlers

  • 無論是 MyBatis 在預(yù)處理語句(PreparedStatement)中設(shè)置一個參數(shù)時,還是從結(jié)果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉(zhuǎn)換成 Java 類型。下表描述了一些默認(rèn)的類型處理器。



  • 你可以重寫類型處理器或創(chuàng)建你自己的類型處理器來處理不支持的或非標(biāo)準(zhǔn)的類型。 具體做法為:實現(xiàn) org.apache.ibatis.type.TypeHandler 接口, 或繼承一個很便利的類 org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個 JDBC 類型。
    // ExampleTypeHandler.java
    @MappedJdbcTypes(JdbcType.VARCHAR)
    public class ExampleTypeHandler extends BaseTypeHandler {

      @Override
      public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
      }

      @Override
      public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getString(columnName);
      }

      @Override
      public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getString(columnIndex);
      }

      @Override
      public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getString(columnIndex);
      }
    }
<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

使用這個的類型處理器將會覆蓋已經(jīng)存在的處理 Java 的 String 類型屬性和 VARCHAR 參數(shù)及結(jié)果的類型處理器。 要注意 MyBatis 不會窺探數(shù)據(jù)庫元信息來決定使用哪種類型,所以你必須在參數(shù)和結(jié)果映射中指明那是 VARCHAR 類型的字段, 以使其能夠綁定到正確的類型處理器上。 這是因為:MyBatis 直到語句被執(zhí)行才清楚數(shù)據(jù)類型。

通過類型處理器的泛型,MyBatis 可以得知該類型處理器處理的 Java 類型,不過這種行為可以通過兩種方法改變:
1)在類型處理器的配置元素(typeHandler element)上增加一個 javaType 屬性(比如:javaType="String");
2)在類型處理器的類上(TypeHandler class)增加一個 @MappedTypes 注解來指定與其關(guān)聯(lián)的 Java 類型列表。 如果在 javaType 屬性中也同時指定,則注解方式將被忽略。

可以通過兩種方式來指定被關(guān)聯(lián)的 JDBC 類型:
1)在類型處理器的配置元素上增加一個 javaType 屬性(比如:javaType="VARCHAR");
2)在類型處理器的類上(TypeHandler class)增加一個 @MappedJdbcTypes 注解來指定與其關(guān)聯(lián)的 JDBC 類型列表。 如果在 javaType 屬性中也同時指定,則注解方式將被忽略。
最后,可以讓 MyBatis 為你查找類型處理器:

<!-- mybatis-config.xml -->
<typeHandlers>
  <package name="org.mybatis.example"/>
</typeHandlers>

注意在使用自動檢索(autodiscovery)功能的時候,只能通過注解方式來指定 JDBC 的類型。
你能創(chuàng)建一個泛型類型處理器,它可以處理多于一個類。為達到此目的, 需要增加一個接收該類作為參數(shù)的構(gòu)造器,這樣在構(gòu)造一個類型處理器的時候 MyBatis 就會傳入一個具體的類。

    //GenericTypeHandler.java
    public class GenericTypeHandler extends BaseTypeHandler {

      private Class type;

      public GenericTypeHandler(Class type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
      }
      ...

EnumTypeHandler 和 EnumOrdinalTypeHandler 都是泛型類型處理器(generic TypeHandlers)

2.5 處理枚舉類型

  • 若想映射枚舉類型 Enum,則需要從 EnumTypeHandler 或者 EnumOrdinalTypeHandler 中選一個來使用。
    比如說我們想存儲取近似值時用到的舍入模式。默認(rèn)情況下,MyBatis 會利用 EnumTypeHandler 來把 Enum 值轉(zhuǎn)換成對應(yīng)的名字。
    注意 EnumTypeHandler 在某種意義上來說是比較特別的,其他的處理器只針對某個特定的類,而它不同,它會處理任意繼承了 Enum 的類。
    不過,我們可能不想存儲名字,相反我們的 DBA 會堅持使用整形值代碼。那也一樣輕而易舉: 在配置文件中把 EnumOrdinalTypeHandler 加到 typeHandlers 中即可, 這樣每個 RoundingMode 將通過他們的序數(shù)值來映射成對應(yīng)的整形。
<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/>
</typeHandlers>
  • 但是怎樣能將同樣的 Enum 既映射成字符串又映射成整形呢?
    自動映射器(auto-mapper)會自動地選用 EnumOrdinalTypeHandler 來處理, 所以如果我們想用普通的 EnumTypeHandler,就非要為那些 SQL 語句顯式地設(shè)置要用到的類型處理器不可。
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
    <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="funkyNumber" property="funkyNumber"/>
        <result column="roundingMode" property="roundingMode"/>
    </resultMap>

    <select id="getUser" resultMap="usermap">
        select * from users
    </select>
    <insert id="insert">
        insert into users (id, name, funkyNumber, roundingMode) values (
            #{id}, #{name}, #{funkyNumber}, #{roundingMode}
        )
    </insert>

    <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="funkyNumber" property="funkyNumber"/>
        <result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
    </resultMap>
    <select id="getUser2" resultMap="usermap2">
        select * from users2
    </select>
    <insert id="insert2">
        insert into users2 (id, name, funkyNumber, roundingMode) values (
            #{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
        )
    </insert>

</mapper>

注意,這里的 select 語句強制使用 resultMap 來代替 resultType。

2.6 對象工廠(objectFactory)

  • MyBatis 每次創(chuàng)建結(jié)果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。 默認(rèn)的對象工廠需要做的僅僅是實例化目標(biāo)類,要么通過默認(rèn)構(gòu)造方法,要么在參數(shù)映射存在的時候通過參數(shù)構(gòu)造方法來實例化。 如果想覆蓋對象工廠的默認(rèn)行為,則可以通過創(chuàng)建自己的對象工廠來實現(xiàn)。比如:
    // ExampleObjectFactory.java
    public class ExampleObjectFactory extends DefaultObjectFactory {
      public Object create(Class type) {
        return super.create(type);
      }
      public Object create(Class type, List constructorArgTypes, List constructorArgs) {
        return super.create(type, constructorArgTypes, constructorArgs);
      }
      public void setProperties(Properties properties) {
        super.setProperties(properties);
      }
      public  boolean isCollection(Class type) {
        return Collection.class.isAssignableFrom(type);
      }}
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
  <property name="someProperty" value="100"/>
</objectFactory>

ObjectFactory 接口很簡單,它包含兩個創(chuàng)建用的方法,一個是處理默認(rèn)構(gòu)造方法的,另外一個是處理帶參數(shù)的構(gòu)造方法的。 最后,setProperties 方法可以被用來配置 ObjectFactory,在初始化你的 ObjectFactory 實例后, objectFactory 元素體中定義的屬性會被傳遞給 setProperties 方法。

2.7 插件(plugins)

  • MyBatis 允許你在已映射語句執(zhí)行過程中的某一點進行攔截調(diào)用。默認(rèn)情況下,MyBatis 允許使用插件來攔截的方法調(diào)用包括:
    1)Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    2)ParameterHandler (getParameterObject, setParameters)
    3)ResultSetHandler (handleResultSets, handleOutputParameters)
    4)StatementHandler (prepare, parameterize, batch, update, query)
    這些類中方法的細(xì)節(jié)可以通過查看每個方法的簽名來發(fā)現(xiàn),或者直接查看 MyBatis 的發(fā)行包中的源代碼。 假設(shè)你想做的不僅僅是監(jiān)控方法的調(diào)用,那么你應(yīng)該很好的了解正在重寫的方法的行為。 因為如果在試圖修改或重寫已有方法的行為的時候,你很可能在破壞 MyBatis 的核心模塊。 這些都是更低層的類和方法,所以使用插件的時候要特別當(dāng)心。

  • 通過 MyBatis 提供的強大機制,使用插件是非常簡單的,只需實現(xiàn) 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="someProperty" value="100"/>
  </plugin>
</plugins> 

上面的插件將會攔截在 Executor 實例中所有的 "update" 方法調(diào)用, 這里的 Executor 是負(fù)責(zé)執(zhí)行低層映射語句的內(nèi)部對象。

  • NOTE 覆蓋配置類
    除了用插件來修改 MyBatis 核心行為之外,還可以通過完全覆蓋配置類來達到目的。只需繼承后覆蓋其中的每個方法,再把它傳遞到 sqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,這可能會嚴(yán)重影響 MyBatis 的行為,務(wù)請慎之又慎。

2.8 配置環(huán)境(environments)

  • MyBatis 可以配置成適應(yīng)多種環(huán)境,這種機制有助于將 SQL 映射應(yīng)用于多種數(shù)據(jù)庫之中, 現(xiàn)實情況下有多種理由需要這么做。例如,開發(fā)、測試和生產(chǎn)環(huán)境需要有不同的配置;或者共享相同 Schema 的多個生產(chǎn)數(shù)據(jù)庫, 想使用相同的 SQL 映射。許多類似的用例。
    不過要記住:盡管可以配置多個環(huán)境,每個 SqlSessionFactory 實例只能選擇其一。
    所以,如果你想連接兩個數(shù)據(jù)庫,就需要創(chuàng)建兩個 SqlSessionFactory 實例,每個數(shù)據(jù)庫對應(yīng)一個。而如果是三個數(shù)據(jù)庫,就需要三個實例,依此類推,記起來很簡單:
    每個數(shù)據(jù)庫對應(yīng)一個 SqlSessionFactory 實例

  • 為了指定創(chuàng)建哪種環(huán)境,只要將它作為可選的參數(shù)傳遞給 SqlSessionFactoryBuilder 即可??梢越邮墉h(huán)境配置的兩個方法簽名是:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);

如果忽略了環(huán)境參數(shù),那么默認(rèn)環(huán)境將會被加載,如下所示:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);

環(huán)境元素定義了如何配置環(huán)境。

<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>
  • 注意這里的關(guān)鍵點:
    1)默認(rèn)的環(huán)境 ID(比如:default="development")。
    2)每個 environment 元素定義的環(huán)境 ID(比如:id="development")。
    3)事務(wù)管理器的配置(比如:type="JDBC")。
    4)數(shù)據(jù)源的配置(比如:type="POOLED")。
    默認(rèn)的環(huán)境和環(huán)境 ID 是一目了然的。隨你怎么命名,只要保證默認(rèn)環(huán)境要匹配其中一個環(huán)境ID。

  • 事務(wù)管理器(transactionManager)
    在 MyBatis 中有兩種類型的事務(wù)管理器(也就是 type="[JDBC|MANAGED]"):
    1)JDBC – 這個配置就是直接使用了 JDBC 的提交和回滾設(shè)置,它依賴于從數(shù)據(jù)源得到的連接來管理事務(wù)范圍。
    2)MANAGED – 這個配置幾乎沒做什么。它從來不提交或回滾一個連接,而是讓容器來管理事務(wù)的整個生命周期(比如 JEE 應(yīng)用服務(wù)器的上下文)。 默認(rèn)情況下它會關(guān)閉連接,然而一些容器并不希望這樣,因此需要將 closeConnection 屬性設(shè)置為 false 來阻止它默認(rèn)的關(guān)閉行為。例如:

<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>

NOTE : 如果你正在使用 Spring + MyBatis,則沒有必要配置事務(wù)管理器, 因為 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
這兩種事務(wù)管理器類型都不需要任何屬性。它們不過是類型別名,換句話說,你可以使用 TransactionFactory 接口的實現(xiàn)類的完全限定名或類型別名代替它們。

    public interface TransactionFactory {
      void setProperties(Properties props);
      Transaction newTransaction(Connection conn);
      Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
    }

任何在 XML 中配置的屬性在實例化之后將會被傳遞給 setProperties() 方法。你也需要創(chuàng)建一個 Transaction 接口的實現(xiàn)類,這個接口也很簡單:

    public interface Transaction {
      Connection getConnection() throws SQLException;
      void commit() throws SQLException;
      void rollback() throws SQLException;
      void close() throws SQLException;
    }

使用這兩個接口,你可以完全自定義 MyBatis 對事務(wù)的處理。

  • 數(shù)據(jù)源(dataSource)
    dataSource 元素使用標(biāo)準(zhǔn)的 JDBC 數(shù)據(jù)源接口來配置 JDBC 連接對象的資源。
    1)許多 MyBatis 的應(yīng)用程序?qū)词纠械睦觼砼渲脭?shù)據(jù)源。然而它并不是必須的。要知道為了方便使用延遲加載,數(shù)據(jù)源才是必須的。

  • 有三種內(nèi)建的數(shù)據(jù)源類型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
    1)UNPOOLED– 這個數(shù)據(jù)源的實現(xiàn)只是每次被請求時打開和關(guān)閉連接。雖然有一點慢,它對在及時可用連接方面沒有性能要求的簡單應(yīng)用程序是一個很好的選擇。 不同的數(shù)據(jù)庫在這方面表現(xiàn)也是不一樣的,所以對某些數(shù)據(jù)庫來說使用連接池并不重要,這個配置也是理想的。UNPOOLED 類型的數(shù)據(jù)源僅僅需要配置以下 5 種屬性:
    1-1)driver – 這是 JDBC 驅(qū)動的 Java 類的完全限定名(并不是JDBC驅(qū)動中可能包含的數(shù)據(jù)源類)。
    1-2)url – 這是數(shù)據(jù)庫的 JDBC URL 地址。
    1-3)username – 登錄數(shù)據(jù)庫的用戶名。
    1-4)password – 登錄數(shù)據(jù)庫的密碼。
    1-4)defaultTransactionIsolationLevel – 默認(rèn)的連接事務(wù)隔離級別。
    作為可選項,你也可以傳遞屬性給數(shù)據(jù)庫驅(qū)動。要這樣做,屬性的前綴為"driver.",例如:driver.encoding=UTF8
    這將通過DriverManager.getConnection(url,driverProperties)方法傳遞值為 UTF8 的 encoding 屬性給數(shù)據(jù)庫驅(qū)動。
    2)POOLED– 這種數(shù)據(jù)源的實現(xiàn)利用"池"的概念將 JDBC 連接對象組織起來,避免了創(chuàng)建新的連接實例時所必需的初始化和認(rèn)證時間。 這是一種使得并發(fā) Web 應(yīng)用快速響應(yīng)請求的流行處理方式。
    除了上述提到 UNPOOLED 下的屬性外,會有更多屬性用來配置 POOLED 的數(shù)據(jù)源:
    2-1)poolMaximumActiveConnections – 在任意時間可以存在的活動(也就是正在使用)連接數(shù)量,默認(rèn)值:10
    2-2)poolMaximumIdleConnections – 任意時間可能存在的空閑連接數(shù)。
    2-3)poolMaximumCheckoutTime – 在被強制返回之前,池中連接被檢出(checked out)時間,默認(rèn)值:20000 毫秒(即 20 秒)
    2-4)poolTimeToWait – 這是一個底層設(shè)置,如果獲取連接花費的相當(dāng)長的時間,它會給連接池打印狀態(tài)日志并重新嘗試獲取一個連接(避免在誤配置的情況下一直安靜的失敗),默認(rèn)值:20000 毫秒(即 20 秒)。
    2-5)poolPingQuery – 發(fā)送到數(shù)據(jù)庫的偵測查詢,用來檢驗連接是否處在正常工作秩序中并準(zhǔn)備接受請求。默認(rèn)是"NO PING QUERY SET",這會導(dǎo)致多數(shù)數(shù)據(jù)庫驅(qū)動失敗時帶有一個恰當(dāng)?shù)腻e誤消息。
    2-6)poolPingEnabled – 是否啟用偵測查詢。若開啟,也必須使用一個可執(zhí)行的 SQL 語句設(shè)置 poolPingQuery 屬性(最好是一個非??斓?SQL),默認(rèn)值:false。
    2-7)poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的使用頻度。這可以被設(shè)置成匹配具體的數(shù)據(jù)庫連接超時時間,來避免不必要的偵測,默認(rèn)值:0(即所有連接每一時刻都被偵測 — 當(dāng)然僅當(dāng) poolPingEnabled 為 true 時適用)。
    3)JNDI– 這個數(shù)據(jù)源的實現(xiàn)是為了能在如 EJB 或應(yīng)用服務(wù)器這類容器中使用,容器可以集中或在外部配置數(shù)據(jù)源,然后放置一個 JNDI 上下文的引用。這種數(shù)據(jù)源配置只需要兩個屬性:
    3-1)initial_context – 這個屬性用來在 InitialContext 中尋找上下文(即,initialContext.lookup(initial_context))。這是個可選屬性,如果忽略,那么 data_source 屬性將會直接從 InitialContext 中尋找。
    3-2)data_source – 這是引用數(shù)據(jù)源實例位置的上下文的路徑。提供了 initial_context 配置時會在其返回的上下文中進行查找,沒有提供時則直接在 InitialContext 中查找。
    和其他數(shù)據(jù)源配置類似,可以通過添加前綴"env."直接把屬性傳遞給初始上下文。比如:env.encoding=UTF8
    這就會在初始上下文(InitialContext)實例化時往它的構(gòu)造方法傳遞值為 UTF8 的 encoding 屬性。
    通過需要實現(xiàn)接口 org.apache.ibatis.datasource.DataSourceFactory , 也可使用任何第三方數(shù)據(jù)源,:

    public interface DataSourceFactory {
      void setProperties(Properties props);
      DataSource getDataSource();
    }

org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory 可被用作父類來構(gòu)建新的數(shù)據(jù)源適配器,比如下面這段插入 C3P0 數(shù)據(jù)源所必需的代碼:

    import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
    import com.mchange.v2.c3p0.ComboPooledDataSource;

    public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

      public C3P0DataSourceFactory() {
        this.dataSource = new ComboPooledDataSource();
      }
    }

為了令其工作,為每個需要 MyBatis 調(diào)用的 setter 方法中增加一個屬性。下面是一個可以連接至 PostgreSQL 數(shù)據(jù)庫的例子:

<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>

2.9 databaseIdProvider

MyBatis 可以根據(jù)不同的數(shù)據(jù)庫廠商執(zhí)行不同的語句,這種多廠商的支持是基于映射語句中的 databaseId 屬性。 MyBatis 會加載不帶 databaseId 屬性和帶有匹配當(dāng)前數(shù)據(jù)庫 databaseId 屬性的所有語句。 如果同時找到帶有 databaseId 和不帶 databaseId 的相同語句,則后者會被舍棄。 為支持多廠商特性只要像下面這樣在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:

<databaseIdProvider type="DB_VENDOR" />

這里的 DB_VENDOR 會通過 DatabaseMetaData#getDatabaseProductName() 返回的字符串進行設(shè)置。 由于通常情況下這個字符串都非常長而且相同產(chǎn)品的不同版本會返回不同的值,所以最好通過設(shè)置屬性別名來使其變短,如下:

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>        
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

在有 properties 時,DB_VENDOR databaseIdProvider 的將被設(shè)置為第一個能匹配數(shù)據(jù)庫產(chǎn)品名稱的屬性鍵對應(yīng)的值,如果沒有匹配的屬性將會設(shè)置為 "null"。 在這個例子中,如果 getDatabaseProductName() 返回"Oracle (DataDirect)",databaseId 將被設(shè)置為"oracle"。

你可以通過實現(xiàn)接口


    public interface DatabaseIdProvider {
      void setProperties(Properties p);
      String getDatabaseId(DataSource dataSource) throws SQLException;
    }

2.10 映射器(mappers)

既然 MyBatis 的行為已經(jīng)由上述元素配置完了,我們現(xiàn)在就要定義 SQL 映射語句了。但是首先我們需要告訴 MyBatis 到哪里去找到這些語句。 Java 在自動查找這方面沒有提供一個很好的方法,所以最佳的方式是告訴 MyBatis 到哪里去找映射文件。你可以使用相對于類路徑的資源引用, 或完全限定資源定位符(包括 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>

這些配置會告訴了 MyBatis 去哪里找映射文件,剩下的細(xì)節(jié)就應(yīng)該是每個 SQL 映射文件了,也就是接下來我們要討論的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,227評論 0 4
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲過程和高級映射...
    有_味閱讀 3,176評論 0 26
  • 812.12.24 10-12點,13-18點 總結(jié) 知識不一定改變你,經(jīng)歷才會(學(xué)習(xí)就是建立n聯(lián)系)。多經(jīng)歷,多...
    宇智博閱讀 378評論 0 0
  • 昨天晚上參加了一個宣講會,關(guān)于南方基金的。聽的有些心馳神往,想要去南方工作了。雖然心里也明白,自己跟候選者這個級別...
    孔瑞杰閱讀 269評論 0 0
  • 第一章 九月出生 一九七六年的邱家村,重男輕女思想還很嚴(yán)重,生個兒子就是生個勞動力,生個女兒...
    中年人甲乙閱讀 369評論 0 0

友情鏈接更多精彩內(nèi)容