天天看點

MyBatis 3.4.0 版本功能介紹

這裡隻列舉部分重要的内容,詳細内容看​​官方說明​​

新增功能

1. Cursor 新增傳回值類型為遊标的方法

當查詢大量(上百萬)資料的時候,使用遊标可以有效的減少記憶體使用,不需要一次性将所有資料得到,可以通過遊标逐個或者分批(逐個擷取一批後)處理。

​SqlSession​

​ 中新增的 3 個遊标方法:

/**
 * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
 * @param <T> the returned cursor element type.
 * @param statement Unique identifier matching the statement to use.
 * @return
<T> Cursor<T> selectCursor(String statement);

/**
 * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
 * @param <T> the returned cursor element type.
 * @param statement Unique identifier matching the statement to use.
 * @param parameter A parameter object to pass to the statement.
 * @return
<T> Cursor<T> selectCursor(String statement, Object parameter);

/**
 * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
 * @param <T> the returned cursor element type.
 * @param statement Unique identifier matching the statement to use.
 * @param parameter A parameter object to pass to the statement.
 * @param rowBounds  Bounds to limit object retrieval
 * @return      

注意: 3.4.0 版本的遊标方法目前有個 bug,是以不支援 ​

​@Select​

​ 注解方式,在将來的 3.4.1 版本中會解決這個問題。

使用示例:

<select id="selectAll" resultType="tk.mybatis.springboot.model.City">
  select * from city
</select>      

xml 裡面沒有任何改變,在擷取值的地方有變化,例如使用接口:

Cursor<City> selectAll();      

或者使用命名接口方式:

Cursor<City> cityList = sqlSession.selectCursor("selectAll");      

得到結果後,使用方法如下:

Iterator<City> iterator = cityList.iterator();
while(iterator.hasNext()){
    City c2 = iterator.next();
    Assert.assertNotNull(c2);
    Assert.assertNotNull(c2.getName());
    Assert.assertNotNull(c2.getState());
}      

嵌套查詢的情況

當使用嵌套查詢時,還需要設定​

​resultOrdered="true"​

​屬性,使用方法如下:

<select id="selectAll" resultMap="xx.CityMap" resultOrdered="true">      

隻有設定這個屬性才能得到目前對象 ​

​id​

​ 所對應的所有嵌套結果。

對某一個嵌套查詢,設定 ​

​resultOrdered="true"​

​ 的結果:

MyBatis 3.4.0 版本功能介紹

不設定的結果:

MyBatis 3.4.0 版本功能介紹

以上圖為例,判斷是否為同一個結果下的對象,使用 id 判斷的,這個 id 必須是 ​

​<resultMap>​

​​ 中的 ​

​<id>​

​​,另外為了結果完整,你還需要按照 ​

​<id>​

​​ 配置的列進行排序,如果結果不是 ​

​<id>​

​ 對應列的順序,嵌套的結果數量會出錯。

2. 增加對 Java 8 日期(JSR-310)的支援

添加以下依賴:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-typehandlers-jsr310</artifactId>
  <version>1.0.0</version>
</dependency>      

如果你使用的 3.4.0 版本,就不需要任何配置就可以直接用。

如果你使用的老版本,需要手動配置:

<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.InstantTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.LocalDateTimeTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.LocalDateTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.LocalTimeTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.OffsetDateTimeTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.OffsetTimeTypeHandler"
  <typeHandler handler="org.apache.ibatis.type.ZonedDateTimeTypeHandler"
</typeHandlers>      

有關 mybatis-typehandlers-jsr310 項目的詳細資訊看​​這裡​​

3. 新增 autoMappingUnknownColumnBehavior 參數

新增了一個 settings 配置的參數 ​

​autoMappingUnknownColumnBehavior​

​ ,當檢測出未知列(或未知屬性)時,如何處理,預設情況下沒有任何提示,這在測試的時候很不友善,不容易找到錯誤。

可選值:

  • NONE : 不做任何處理 (預設值)
  • WARNING : 警告日志形式的詳細資訊
  • FAILING : 映射失敗,抛出異常和詳細資訊

配置時,在 ​

​<settings>​

​ 裡面添加:

<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>      

4. Sql Provider 注解方式支援多個參數

例如:

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
    @Param("name") String name,
    @Param("orderByColumn") String orderByColumn); // Multiple arguments      

在寫 ​

​UserSqlBuilder​

​ 的時候,同樣需要使用注解來指定參數(或者按順序):

public String buildGetUsersByName(
    @Param("name") final String name
    @Param("orderByColumn") final String orderByColumn) { // Allow multiple arguments
    return new SQL(){{
        SELECT("*");
        FROM("users");
        if (name != null) {
            WHERE("name like #{name} || '%'");
        }
        ORDER_BY(orderByColumn);
    }}.toString();
}      

解決的 BUG

支援實體類中的泛型類型

例如 ​

​Entity​

​ 基類:

public abstract class Entity<K extends Serializable>  {
    private static final long serialVersionUID = -1L;
    protected K id;

    public K getId() {
        return id;
    }

    public void setId(K id) {
        this.id = id;
    }      
public class User extends Entity<String>