1. 程式人生 > >MyBatis實戰之配置

MyBatis實戰之配置

MyBatis最重要的配置也就兩個,一個是mybatis-config.xml,又稱MyBatis的全域性配置,另一個就是XXXDao.xml或XXXMapper.xml對映配置。

今天主要講的兩個配置就是這兩個。

一、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> <typeAliases> <package name="com.blog.entity"/> </typeAliases> <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://127.0.0.1:3306/blog_test"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments>
<mappers> <mapper resource="mybatis/mapping/UserDao.xml"/> </mappers> </configuration>

 

1.properties元素

properties是一個配置屬性的元素,讓我們能在配置檔案的上下文使用它。

MyBatis提供3種配置方式。

(1)properties子元素(如上述);

(2)properties配置檔案(例如讀取jdbc.properties配置檔案,這個在spring-mybatis整合得以體現);

(3)程式引數傳遞(本質上是讀取properties配置檔案,通過鍵值對的讀取並傳遞引數);

 

關於它們的優先順序

首先,properties元素體內指定的屬性首先被讀取;

其次,根據properties元素中的resource屬性讀取類路徑下屬性檔案,或者根據url屬性指定的路徑讀取屬性檔案,並覆蓋已讀取的同名屬性;

最後,讀取作為方法引數傳遞的屬性,並覆蓋已讀取的同名屬性;

因此,通過方法引數傳遞的屬性具有最高優先順序,resource/url屬性中指定的配置檔案次之,最低優先順序的是properties屬性中指定的屬性。因此,實際操作中我們需要注意以下三點:

(1)不要使用混合的方式,這樣會使得管理混亂;

(2)首先方式是使用properties檔案;

(3)如果我們需要對其進行加密或者其他加工以滿足特殊的要求,不妨按照程式引數傳遞方式;

 

 

2.設定

設定(settings)在MyBatis中是最複雜的配置,同時也是最為重要的配置內容之一,它會改變MyBatis執行時的行為。即使不配置settings,MyBatis也可以正常的工作,不過了解settings的配置內容,以及它們的作用仍然十分必要。

 

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

 

3.別名

MyBatis系統定義了一些經常使用的型別的別名,例如,數值、字串、日期和集合等,我們可以在MyBatis中直接使用它們,在使用時不要重複定義把它們給覆蓋了。

讓我們看看MyBatis已經定義好的別名(支援陣列型別的只要加"[]" 即可使用,比如Date數組別名可以用date[]代替)。

系統定義的typeAliases 如圖所示:

圖一:

 

 圖二:

 

圖三:

 

我們在MyBatis實戰之初步 說到過別名和它的三種配置方式,所以此處不再贅述。

 

4.typeHandler型別處理器

MyBatis在預處理語句(PreparedStatement)中設定一個引數時,或者從結果集(ResultSet)中取出一個值,都會用註冊了的typeHandler進行處理。

由於資料庫可能來自不同廠商,不同的廠商設定的引數可能存在差異,同時資料庫也可以自定義資料型別,typeHandler允許根據專案的需要自定義設定Java傳遞到資料庫的引數中,或者從資料庫讀出資料,我們也需要進行特殊的處理,這些都可以在定義的typeHandler中處理,尤其在使用列舉的時候我們常常需要使用typeHandler進行轉換。

typeHandler和別名一樣,分為MyBatis系統定義和使用者自定義兩種。一般來說,使用MyBatis系統定義就可以實現大部分的功能,如果使用使用者自定義的typeHandler,我們在處理的時候務必小心謹慎,以避免出現不必要的錯誤。

typeHandler 常用的配置為Java型別(javaType)、JDBC型別(jdbcType)。typeHandler的作用就是將引數從javaType轉化為jdbcType,或者從資料庫取出結果時把jdbcType轉化為javaType。

 

系統註冊的typeHandle簡介,如下圖所示:

圖一:

 

圖二:

 

 需要注意以下幾點?

(1)數值型別的精度,資料庫Int、double、decimal這些型別和Java的精度、長度都是不一樣的;

(2)時間精度,取資料到日用DateOnlyTypeHandler即可,用到精度為秒的用SqlTimestamp、TypeHandler等;

 

讓我們選取一個MyBatis系統自定義的typeHandler,並瞭解它的具體內容。我們可以看到MyBatis原始碼包org.apache.ibatis.type下面定義的StringTypeHandler。StringTypeHandler是一個常用的typeHandler,負責處理String型別。

 

StringTypeHandler原始碼如下:

 *    Copyright 2009-2015 the original author or authors.
package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Clinton Begin
 */
public class StringTypeHandler extends BaseTypeHandler<String> {

  @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);
  }
}

 

 說明一下上面的程式碼:

StringTypeHandler繼承BaseTypeHandler,而BaseTypeHandler實現介面typeHandler,並且自己定義了4個抽象的方法。所以繼承它的時候,正如本例一樣,正如本例一樣需要實現其定義的4個抽象方法,這些方法已經在StringTypeHandler中用@Override註解註明了。

setParameter是PreparedStatement物件設定引數,它允許我們自己填寫變換規則。

getResult則分為ResultSet用列名(columnName)或者使用列下標(columnIndex)來獲取結果資料。其中還包括了用CallableStatement(儲存過程)獲取結果及資料的方法。

 

如果你想自定義Handler,除了編寫一個Java類之外,還需要在mybatis-config.xml配置如下內容:

  <typeHandlers>
  <typeHandler handler="com.blog.typehandler.MyStringHandler" javaType="string" jdbcType="varchar"/>
  </typeHandlers>

 

5.ObjectFactory

當MyBatis在構建一個結果返回的時候,都會使用ObjectFactory(物件工廠)去構建POJO,在MyBatis中可以定製自己的物件工廠。一般來說我們使用預設的ObjectFactory即可,MyBatis中預設的ObjectFactory是由org.apache.ibatis.reflection.factory.DefaultObjectFactory來提供的。在大部分的場景下我們都不用修改,如果要定製特定的工廠則需要進行配置。

例如我們自定義個ObjectFactory就需要在mybatis-config.xml配置如下內容:

    <objectFactory type="com.blog.custom.MyObjectFactory">
        <property name="userName" value="MyObjectFacotry"/>
    </objectFactory>

 

6.外掛

外掛是比較複雜的,使用時要特別小心。使用外掛將覆蓋一些MyBatis內部核心物件的行為,在沒有了解MyBatiss內部執行原理之前我們沒有必要去討論它,後面會說的。

 

7.environment配置環境

配置環境可以註冊多個數據源,每個資料來源分為兩大部分,一個是資料庫源的配置,另一個是資料庫事務的配置。

資料來源配置如下:

 <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://127.0.0.1:3306/blog_test"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
      </dataSource>
    </environment>
  </environments>

分析下上述配置:

(1)environments中的屬性default,標明在預設的情況下,我們將啟動哪個資料來源配置;

(2)environment元素是配置一個數據源的開始,屬性id是設定這個資料來源的標誌,以便MyBatis上下文使用它;

(3)transactionManager配置的資料庫事務,其中type屬性有三種配置方式:

a.JDBC,採用JDBC方式管理事務,在獨立編碼中我們常常使用;

b.MANAGED,採用容器方式管理事務,在JNDI資料來源中常用;

c.自定義,由使用者自定義資料庫事務管理辦法,適用於特殊應用。

(4)property元素則是可以配置資料來源的各類屬性,假如在此配置autoCommit=false,則是要求資料來源不自動提交,預設情況是自動提交;

(5)dataSource標籤,是配置資料來源連線的資訊,type屬性是提供我們對資料庫連線方式的配置,同樣MyBatis提供了這麼幾種配置方式:

a.UNPOOLED,非連線池資料庫;

b.POOLED,連線池資料庫;

c.JNDI,JNDI資料來源;

d.自定義資料來源;

其中,配置的property元素,就是定義資料庫的各類引數。

關於資料庫事務MyBatis,它是由SqlSession去控制的,我們通過SqlSession提交或者回滾。我們插入一個角色物件,如果成功就提交,否則就回滾。不過大部分情況都是由Spring框架去控制。後面會講到。

 

MyBatis內部為我們提供三種資料來源的實現方式:

(1)UNPOOLED,非連線池,使用MyBatis提供的org.apache.ibatis.datasource.unpooled.UnpooledDataSource實現;

(2)POOLED,連線池,使用MyBatis提供的org.apache.ibatis.datasource.pooled.PooledDataSource實現;

(3)JNDI,使用MyBatis提供的org.apache.ibatis.datasource.jndi.JndiDataSourceFactory來獲取資料來源;

我們只需把資料來源的屬性type定義為UNPOOLED、POOLED、JNDI即可。

 

9.databaseIdProvider 資料庫廠商標識

在相同資料庫廠商的環境下,資料庫廠商標識沒有什麼意義,在實際的應用中使用得比較少,因為使用不同廠商資料庫的系統還是比較少的。MyBatis可能會執行在不同廠商的資料庫中,它為此提供一個數據庫標識,並提供自定義,它的作用在於指定SQL到對應的資料庫廠商提供的資料庫中執行。

這個不是特別重要,在此不詳說,告訴讀者有個這玩意。