欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于MyBatis中SqlSessionFactory和SqlSession簡解

 更新時間:2021年12月16日 11:40:04   作者:流煙默  
這篇文章主要介紹了MyBatis中SqlSessionFactory和SqlSession簡解,具有很好的參考價值,希望大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

mybatis官網(wǎng)中文文檔:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

mybatis-spring官方中文文檔:https://mybatis.org/spring/zh/index.html

【1】SqlSessionFactoryBuilder

這個類可以被初始化、使用和丟棄,如果你已經(jīng)創(chuàng)建好了一個SqlSessionFactory 后就不用再保留它。

因此,SqlSessionFactoryBuilder 的最好作用域是方法體內(nèi)

比如說定義一個方法變量。你可以重復(fù)使用SqlSessionFactoryBuilder 生成多個SqlSessionFactory 實例,但是最好不要強(qiáng)行保留,因為XML 的解析資源要用來做其它更重要的事。

mybatis3.4.1版本中,SqlSessionFactoryBuilder中獲取SqlSessionFactory實例如下(每一種都允許你從不同的資源中創(chuàng)建一個 SqlSessionFactory 實例):

SqlSessionFactory build(Reader reader)
SqlSessionFactory build(Reader reader, String environment) 
SqlSessionFactory build(Reader reader, Properties properties) 
SqlSessionFactory build(Reader reader, String environment, Properties properties)
SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)
SqlSessionFactory build(Configuration config)

SqlSessionFactoryBuilder完整源碼

package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
/**
 * Builds {@link SqlSession} instances.
 *
 * @author Clinton Begin
 */
public class SqlSessionFactoryBuilder {
  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }
  public SqlSessionFactory build(Reader reader, String environment) {
    return build(reader, environment, null);
  }
  public SqlSessionFactory build(Reader reader, Properties properties) {
    return build(reader, null, properties);
  }
//核心方法一
  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
    //這里非常非常重要,會解析mybatis的相關(guān)配置,以及XXXMapper.xml中的結(jié)點、xxxxMapper.java中的注解
      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.
      }
    }
  }
  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }
  public SqlSessionFactory build(InputStream inputStream, String environment) {
    return build(inputStream, environment, null);
  }
  public SqlSessionFactory build(InputStream inputStream, Properties properties) {
    return build(inputStream, null, properties);
  }
//核心方法二
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }
//核心方法三,根據(jù)解析到的Configuration 創(chuàng)建一個默認(rèn)的DefaultSqlSessionFactory
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
}

上面有兩種創(chuàng)建DefaultSqlSessionFactory的核心方法,提供了諸多重載方法,最后調(diào)用核心方法三得到一個默認(rèn)的DefaultSqlSessionFactory實例。

【2】SqlSessionFactory

SqlSessionFactory一旦創(chuàng)建,SqlSessionFactory 就會在整個應(yīng)用過程中始終存在。所以沒有理由去銷毀和再創(chuàng)建它,一個應(yīng)用運(yùn)行中也不建議多次創(chuàng)建SqlSessionFactory。

因此SqlSessionFactory最好的作用域是Application。

可以有多種方法實現(xiàn),最簡單的方法是單例模式或者是靜態(tài)單例模式。然而這也不是廣泛贊成和好用的。反而,使用Google Guice 或Spring 來進(jìn)行依賴反射會更好。這些框架允許你生成管理器來管理SqlSessionFactory 的單例生命周期。

SqlSessionFactory 接口源碼

package org.apache.ibatis.session;
import java.sql.Connection;
/**
根據(jù)一個數(shù)據(jù)庫連接或者數(shù)據(jù)源創(chuàng)建一個sqlsession實例,create..out of 根據(jù)/由什么創(chuàng)建
 * Creates an {@link SqlSession} out of a connection or a DataSource
 * @author Clinton Begin
 */
public interface SqlSessionFactory {
  SqlSession openSession();
  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);
  Configuration getConfiguration();
}

其默認(rèn)實現(xiàn)類是DefaultSqlSessionFactory。

SqlSessionFactory 有六個方法創(chuàng)建 SqlSession 實例

SqlSessionFactory 有六個方法創(chuàng)建 SqlSession 實例。通常來說,當(dāng)你選擇其中一個方法時,你需要考慮以下幾點:

  • 事務(wù)處理:你希望在 session 作用域中使用事務(wù)作用域,還是使用自動提交(auto-commit)?(對很多數(shù)據(jù)庫和/或 JDBC 驅(qū)動來說,等同于關(guān)閉事務(wù)支持)
  • 數(shù)據(jù)庫連接:你希望 MyBatis 幫你從已配置的數(shù)據(jù)源獲取連接,還是使用自己提供的連接?
  • 語句執(zhí)行:你希望 MyBatis 復(fù)用 PreparedStatement 和/或批量更新語句(包括插入語句和刪除語句)嗎?

基于以上需求,有下列已重載的多個 openSession() 方法供使用。

SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();

默認(rèn)的 openSession() 方法沒有參數(shù),它會創(chuàng)建具備如下特性的 SqlSession:

  • 事務(wù)作用域?qū)_啟(也就是不自動提交)。
  • 將由當(dāng)前環(huán)境配置的 DataSource 實例中獲取 Connection 對象。
  • 事務(wù)隔離級別將會使用驅(qū)動或數(shù)據(jù)源的默認(rèn)設(shè)置。
  • 預(yù)處理語句不會被復(fù)用,也不會批量處理更新。

相信你已經(jīng)能從方法簽名中知道這些方法的區(qū)別。向 autoCommit 可選參數(shù)傳遞 true 值即可開啟自動提交功能。若要使用自己的 Connection 實例,傳遞一個 Connection 實例給 connection 參數(shù)即可。注意,我們沒有提供同時設(shè)置 Connection 和 autoCommit 的方法,這是因為 MyBatis 會依據(jù)傳入的 Connection 來決定是否啟用 autoCommit。對于事務(wù)隔離級別,MyBatis 使用了一個 Java 枚舉包裝器來表示,稱為 TransactionIsolationLevel,事務(wù)隔離級別支持 JDBC 的五個隔離級別(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE),并且與預(yù)期的行為一致。

你可能對 ExecutorType 參數(shù)感到陌生。這個枚舉類型定義了三個值:

  • ExecutorType.SIMPLE:該類型的執(zhí)行器沒有特別的行為。它為每個語句的執(zhí)行創(chuàng)建一個新的預(yù)處理語句。
  • ExecutorType.REUSE:該類型的執(zhí)行器會復(fù)用預(yù)處理語句。
  • ExecutorType.BATCH:該類型的執(zhí)行器會批量執(zhí)行所有更新語句,如果 SELECT 在多個更新中間執(zhí)行,將在必要時將多條更新語句分隔開來,以方便理解。

批量操作是在session.commit()以后才發(fā)送sql語句給數(shù)據(jù)庫進(jìn)行執(zhí)行的如果我們想讓其提前執(zhí)行,以方便后續(xù)可能的查詢操作獲取數(shù)據(jù),我們可以使用sqlSession.flushStatements()方法,讓其直接沖刷到數(shù)據(jù)庫進(jìn)行執(zhí)行。

提示 在 SqlSessionFactory 中還有一個方法我們沒有提及,就是 getConfiguration()。這個方法會返回一個 Configuration 實例,你可以在運(yùn)行時使用它來檢查 MyBatis 的配置。

提示 如果你使用過 MyBatis 的舊版本,可能還記得 session、事務(wù)和批量操作是相互獨(dú)立的。在新版本中則不是這樣。上述三者都包含在 session 作用域內(nèi)。你不必分別處理事務(wù)或批量操作就能得到想要的全部效果。

默認(rèn)的openSession() 方法沒有參數(shù),它會創(chuàng)建有如下特性的

  • 會開啟一個事務(wù)(也就是不自動提交)
  • 連接對象會從由活動環(huán)境配置的數(shù)據(jù)源實例得到。
  • 事務(wù)隔離級別將會使用驅(qū)動或數(shù)據(jù)源的默認(rèn)設(shè)置。
  • 預(yù)處理語句不會被復(fù)用,也不會批量處理更新。

【3】非線程安全的SqlSession

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通過這個接口來執(zhí)行命令,獲取映射器實例和管理事務(wù)。

每個線程都有自己的SqlSession 實例,SqlSession 實例是不能被共享,也不是線程安全的。因此最好使用request 作用域或者方法體作用域。

不要使用類的靜態(tài)變量來引用一個SqlSession 實例,甚至不要使用類的一個實例變量來引用。否則,會有線程安全問題。

永遠(yuǎn)不要在一個被管理域中引用SqlSession

比如說在Servlet 中的HttpSession 中。如果你正在使用WEB 框架,應(yīng)該讓SqlSession 跟隨HTTP 請求的相似作用域。也就是說,在收到一個HTTP 請求過后,打開SqlSession,等返回一個回應(yīng)以后,立馬關(guān)掉這個SqlSession。關(guān)閉SqlSession 是非常重要的,你必須要確保SqlSession 在finally 方法體中正常關(guān)閉。

SqlSession可以直接調(diào)用方法的id進(jìn)行數(shù)據(jù)庫操作,但是我們一般還是推薦使用SqlSession獲取到Dao接口的代理類,執(zhí)行代理對象的方法,可以更安全的進(jìn)行類型檢查操作。

如下代碼所示,是調(diào)用方法ID進(jìn)行數(shù)據(jù)庫操作:

SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
	Employee employee = openSession.selectOne(
			"com.mybatis.EmployeeMapper.selectEmp", 1);
	System.out.println(employee);
} finally {
	openSession.close();
}

正如之前所提到的,SqlSession 在 MyBatis 中是非常強(qiáng)大的一個類。它包含了所有執(zhí)行語句、提交或回滾事務(wù)以及獲取映射器實例的方法。

SqlSession 類的方法超過了 20 個,為了方便理解,我們將它們分成幾種組別。

語句執(zhí)行方法

這些方法被用來執(zhí)行定義在 SQL 映射 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 語句。你可以通過名字快速了解它們的作用,每一方法都接受語句的 ID 以及參數(shù)對象,參數(shù)可以是原始類型(支持自動裝箱或包裝類)、JavaBean、POJO 或 Map。

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

selectOne 和 selectList 的不同僅僅是 selectOne 必須返回一個對象或 null 值。如果返回值多于一個,就會拋出異常。如果你不知道返回對象會有多少,請使用 selectList。如果需要查看某個對象是否存在,最好的辦法是查詢一個 count 值(0 或 1)。selectMap 稍微特殊一點,它會將返回對象的其中一個屬性作為 key 值,將對象作為 value 值,從而將多個結(jié)果集轉(zhuǎn)為 Map 類型值。由于并不是所有語句都需要參數(shù),所以這些方法都具有一個不需要參數(shù)的重載形式。

游標(biāo)(Cursor)與列表(List)返回的結(jié)果相同,不同的是,游標(biāo)借助迭代器實現(xiàn)了數(shù)據(jù)的惰性加載。

try (Cursor<MyEntity> entities = session.selectCursor(statement, param)) {
   for (MyEntity entity:entities) {
      // 處理單個實體
   }
}
insert、update 以及 delete 方法返回的值表示受該語句影響的行數(shù)。
<T> T selectOne(String statement)
<E> List<E> selectList(String statement)
<T> Cursor<T> selectCursor(String statement)
<K,V> Map<K,V> selectMap(String statement, String mapKey)
int insert(String statement)
int update(String statement)
int delete(String statement)

最后,還有 select 方法的三個高級版本,它們允許你限制返回行數(shù)的范圍,或是提供自定義結(jié)果處理邏輯,通常在數(shù)據(jù)集非常龐大的情形下使用。

<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)

RowBounds 參數(shù)會告訴 MyBatis 略過指定數(shù)量的記錄,并限制返回結(jié)果的數(shù)量。RowBounds 類的 offset 和 limit 值只有在構(gòu)造函數(shù)時才能傳入,其它時候是不能修改的。

int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);

數(shù)據(jù)庫驅(qū)動決定了略過記錄時的查詢效率。為了獲得最佳的性能,建議將 ResultSet 類型設(shè)置為 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE(換句話說:不要使用 FORWARD_ONLY)。

ResultHandler 參數(shù)允許自定義每行結(jié)果的處理過程。你可以將它添加到 List 中、創(chuàng)建 Map 和 Set,甚至丟棄每個返回值,只保留計算后的統(tǒng)計結(jié)果。你可以使用 ResultHandler 做很多事,這其實就是 MyBatis 構(gòu)建 結(jié)果列表的內(nèi)部實現(xiàn)辦法。

從版本 3.4.6 開始,ResultHandler 會在存儲過程的 REFCURSOR 輸出參數(shù)中傳遞使用的 CALLABLE 語句。

它的接口很簡單:

package org.apache.ibatis.session;
public interface ResultHandler<T> {
  void handleResult(ResultContext<? extends T> context);
}

ResultContext 參數(shù)允許你訪問結(jié)果對象和當(dāng)前已被創(chuàng)建的對象數(shù)目,另外還提供了一個返回值為 Boolean 的 stop 方法,你可以使用此 stop 方法來停止 MyBatis 加載更多的結(jié)果。

使用 ResultHandler 的時候需要注意以下兩個限制:

  • 使用帶 ResultHandler 參數(shù)的方法時,收到的數(shù)據(jù)不會被緩存。
  • 當(dāng)使用高級的結(jié)果映射集(resultMap)時,MyBatis 很可能需要數(shù)行結(jié)果來構(gòu)造一個對象。如果你使用了 ResultHandler,你可能會接收到關(guān)聯(lián)(association)或者集合(collection)中尚未被完整填充的對象。

立即批量更新方法

當(dāng)你將 ExecutorType 設(shè)置為 ExecutorType.BATCH 時,可以使用這個方法清除(執(zhí)行)緩存在 JDBC 驅(qū)動類中的批量更新語句。

List<BatchResult> flushStatements()

事務(wù)控制方法

有四個方法用來控制事務(wù)作用域。當(dāng)然,如果你已經(jīng)設(shè)置了自動提交或你使用了外部事務(wù)管理器,這些方法就沒什么作用了。然而,如果你正在使用由 Connection 實例控制的 JDBC 事務(wù)管理器,那么這四個方法就會派上用場:

void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)

默認(rèn)情況下 MyBatis 不會自動提交事務(wù),除非它偵測到調(diào)用了插入、更新或刪除方法改變了數(shù)據(jù)庫。如果你沒有使用這些方法提交修改,那么你可以在 commit 和 rollback 方法參數(shù)中傳入 true 值,來保證事務(wù)被正常提交(注意,在自動提交模式或者使用了外部事務(wù)管理器的情況下,設(shè)置 force 值對 session 無效)。大部分情況下你無需調(diào)用 rollback(),因為 MyBatis 會在你沒有調(diào)用 commit 時替你完成回滾操作。不過,當(dāng)你要在一個可能多次提交或回滾的 session 中詳細(xì)控制事務(wù),回滾操作就派上用場了。

提示 MyBatis-Spring 和 MyBatis-Guice 提供了聲明式事務(wù)處理,所以如果你在使用 Mybatis 的同時使用了 Spring 或者 Guice,請參考它們的手冊以獲取更多的內(nèi)容。

本地緩存

Mybatis 使用到了兩種緩存:本地緩存(local cache)和二級緩存(second level cache)。

每當(dāng)一個新 session 被創(chuàng)建,MyBatis 就會創(chuàng)建一個與之相關(guān)聯(lián)的本地緩存。任何在 session 執(zhí)行過的查詢結(jié)果都會被保存在本地緩存中,所以,當(dāng)再次執(zhí)行參數(shù)相同的相同查詢時,就不需要實際查詢數(shù)據(jù)庫了。本地緩存將會在做出修改、事務(wù)提交或回滾,以及關(guān)閉 session 時清空。

默認(rèn)情況下,本地緩存數(shù)據(jù)的生命周期等同于整個 session 的周期。由于緩存會被用來解決循環(huán)引用問題和加快重復(fù)嵌套查詢的速度,所以無法將其完全禁用。但是你可以通過設(shè)置 localCacheScope=STATEMENT 來只在語句執(zhí)行時使用緩存。

注意,如果 localCacheScope 被設(shè)置為 SESSION,對于某個對象,MyBatis 將返回在本地緩存中唯一對象的引用。對返回的對象(例如 list)做出的任何修改將會影響本地緩存的內(nèi)容,進(jìn)而將會影響到在本次 session 中從緩存返回的值。因此,不要對 MyBatis 所返回的對象作出更改,以防后患。

你可以隨時調(diào)用以下方法來清空本地緩存:

void clearCache()

確保 SqlSession 被關(guān)閉

void close()

對于你打開的任何 session,你都要保證它們被妥善關(guān)閉,這很重要。保證妥善關(guān)閉的最佳代碼模式是這樣的:

SqlSession session = sqlSessionFactory.openSession();
try (SqlSession session = sqlSessionFactory.openSession()) {
    // 假設(shè)下面三行代碼是你的業(yè)務(wù)邏輯
    session.insert(...);
    session.update(...);
    session.delete(...);
    session.commit();
}

提示 和 SqlSessionFactory 一樣,你可以調(diào)用當(dāng)前使用的 SqlSession 的 getConfiguration 方法來獲得 Configuration 實例。

Configuration getConfiguration()

使用映射器

<T> T getMapper(Class<T> type)

上述的各個 insert、update、delete 和 select 方法都很強(qiáng)大,但也有些繁瑣,它們并不符合類型安全,對你的 IDE 和單元測試也不是那么友好。因此,使用映射器類來執(zhí)行映射語句是更常見的做法。

我們已經(jīng)在之前的入門章節(jié)中見到過一個使用映射器的示例。一個映射器類就是一個僅需聲明與 SqlSession 方法相匹配方法的接口。下面的示例展示了一些方法簽名以及它們是如何映射到 SqlSession 上的。

public interface AuthorMapper {
  // (Author) selectOne("selectAuthor",5);
  Author selectAuthor(int id);
  // (List<Author>) selectList(“selectAuthors”)
  List<Author> selectAuthors();
  // (Map<Integer,Author>) selectMap("selectAuthors", "id")
  @MapKey("id")
  Map<Integer, Author> selectAuthors();
  // insert("insertAuthor", author)
  int insertAuthor(Author author);
  // updateAuthor("updateAuthor", author)
  int updateAuthor(Author author);
  // delete("deleteAuthor",5)
  int deleteAuthor(int id);
}

總之,每個映射器方法簽名應(yīng)該匹配相關(guān)聯(lián)的 SqlSession 方法,字符串參數(shù) ID 無需匹配。而是由方法名匹配映射語句的 ID。

此外,返回類型必須匹配期望的結(jié)果類型,返回單個值時,返回類型應(yīng)該是返回值的類,返回多個值時,則為數(shù)組或集合類,另外也可以是游標(biāo)(Cursor)。所有常用的類型都是支持的,包括:原始類型、Map、POJO 和 JavaBean。

提示 映射器接口不需要去實現(xiàn)任何接口或繼承自任何類。只要方法簽名可以被用來唯一識別對應(yīng)的映射語句就可以了。

提示 映射器接口可以繼承自其他接口。在使用 XML 來綁定映射器接口時,保證語句處于合適的命名空間中即可。唯一的限制是,不能在兩個具有繼承關(guān)系的接口中擁有相同的方法簽名(這是潛在的危險做法,不可?。?。

你可以傳遞多個參數(shù)給一個映射器方法。在多個參數(shù)的情況下,默認(rèn)它們將會以 param 加上它們在參數(shù)列表中的位置來命名,比如:#{param1}、#{param2}等。如果你想(在有多個參數(shù)時)自定義參數(shù)的名稱,那么你可以在參數(shù)上使用 @Param("paramName") 注解。

你也可以給方法傳遞一個 RowBounds 實例來限制查詢結(jié)果。

映射器注解

設(shè)計初期的 MyBatis 是一個 XML 驅(qū)動的框架。配置信息是基于 XML 的,映射語句也是定義在 XML 中的。而在 MyBatis 3 中,我們提供了其它的配置方式。MyBatis 3 構(gòu)建在全面且強(qiáng)大的基于 Java 語言的配置 API 之上。它是 XML 和注解配置的基礎(chǔ)。注解提供了一種簡單且低成本的方式來實現(xiàn)簡單的映射語句。

提示 不幸的是,Java 注解的表達(dá)能力和靈活性十分有限。盡管我們花了很多時間在調(diào)查、設(shè)計和試驗上,但最強(qiáng)大的 MyBatis 映射并不能用注解來構(gòu)建——我們真沒開玩笑。而 C# 屬性就沒有這些限制,因此 MyBatis.NET 的配置會比 XML 有更大的選擇余地。雖說如此,基于 Java 注解的配置還是有它的好處的。

映射注解示例

這個例子展示了如何使用 @SelectKey 注解來在插入前讀取數(shù)據(jù)庫序列的值:

@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
@SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class)
int insertTable3(Name name);

這個例子展示了如何使用 @SelectKey 注解來在插入后讀取數(shù)據(jù)庫自增列的值:

@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);

這個例子展示了如何使用 @Flush 注解來調(diào)用 SqlSession#flushStatements():

@Flush
List<BatchResult> flush();

這些例子展示了如何通過指定 @Result 的 id 屬性來命名結(jié)果集:

@Results(id = "userResult", value = {
  @Result(property = "id", column = "uid", id = true),
  @Result(property = "firstName", column = "first_name"),
  @Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);
@Results(id = "companyResults")
@ConstructorArgs({
  @Arg(column = "cid", javaType = Integer.class, id = true),
  @Arg(column = "name", javaType = String.class)
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);

這個例子展示了如何使用單個參數(shù)的 @SqlProvider 注解:

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);
class UserSqlBuilder {
  public static String buildGetUsersByName(final String name) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      if (name != null) {
        WHERE("name like #{value} || '%'");
      }
      ORDER_BY("id");
    }}.toString();
  }
}

這個例子展示了如何使用多個參數(shù)的 @SqlProvider 注解:

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
    @Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
  // 如果不使用 @Param,就應(yīng)該定義與 mapper 方法相同的參數(shù)
  public static String buildGetUsersByName(
      final String name, final String orderByColumn) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      WHERE("name like #{name} || '%'");
      ORDER_BY(orderByColumn);
    }}.toString();
  }
  // 如果使用 @Param,就可以只定義需要使用的參數(shù)
  public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      WHERE("name like #{name} || '%'");
      ORDER_BY(orderByColumn);
    }}.toString();
  }
}

以下例子展示了通過使用全局配置Configuration 來實現(xiàn)所有mapper方法共享一個 sql provider 類(3.5.6后可用):

Configuration configuration = new Configuration();
configuration.setDefaultSqlProviderType(TemplateFilePathProvider.class);
 // Specify an sql provider class for sharing on all mapper methods
// ...
// Can omit the type/value attribute on sql provider annotation
// If omit it, the MyBatis apply the class that specified on defaultSqlProviderType.
public interface UserMapper {
  @SelectProvider // Same with @SelectProvider(TemplateFilePathProvider.class)
  User findUser(int id);
  @InsertProvider // Same with @InsertProvider(TemplateFilePathProvider.class)
  void createUser(User user);
  @UpdateProvider // Same with @UpdateProvider(TemplateFilePathProvider.class)
  void updateUser(User user);
  @DeleteProvider // Same with @DeleteProvider(TemplateFilePathProvider.class)
  void deleteUser(int id);
}

以下例子展示了 ProviderMethodResolver(3.5.1 后可用)的默認(rèn)實現(xiàn)使用方法:

@SelectProvider(UserSqlProvider.class)
List<User> getUsersByName(String name);
// 在你的 provider 類中實現(xiàn) ProviderMethodResolver 接口
class UserSqlProvider implements ProviderMethodResolver {
  // 默認(rèn)實現(xiàn)中,會將映射器方法的調(diào)用解析到實現(xiàn)的同名方法上
  public static String getUsersByName(final String name) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      if (name != null) {
        WHERE("name like #{value} || '%'");
      }
      ORDER_BY("id");
    }}.toString();
  }
}

以下例子展示了如何在注解上使用databaseId (3.5.5后可用):

@Select(value = "SELECT SYS_GUID() FROM dual", databaseId = "oracle") // Use this statement if DatabaseIdProvider provide "oracle"
@Select(value = "SELECT uuid_generate_v4()", databaseId = "postgres") // Use this statement if DatabaseIdProvider provide "postgres"
@Select("SELECT RANDOM_UUID()") // Use this statement if the DatabaseIdProvider not configured or not matches databaseId
String generateId();

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis入門教程(四)之mybatis動態(tài)sql

    Mybatis入門教程(四)之mybatis動態(tài)sql

    這篇文章主要介紹了Mybatis入門教程(四)之mybatis動態(tài)sql的相關(guān)資料,涉及到動態(tài)sql及動態(tài)sql的作用知識,本文介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • springboot啟動feign項目報錯:Service id not legal hostnam的解決

    springboot啟動feign項目報錯:Service id not legal hostnam的解決

    這篇文章主要介紹了springboot啟動feign項目報錯:Service id not legal hostnam的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 基于SpringBoot實現(xiàn)圖片上傳與顯示

    基于SpringBoot實現(xiàn)圖片上傳與顯示

    這篇文章主要為大家詳細(xì)介紹了基于SpringBoot實現(xiàn)圖片上傳與顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • 面試題:Java 實現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字

    面試題:Java 實現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字

    這篇文章主要介紹了Java 實現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • java實現(xiàn)斗地主游戲

    java實現(xiàn)斗地主游戲

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)斗地主游戲,洗牌、發(fā)牌、看牌,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Java類加載器ClassLoader的使用詳解

    Java類加載器ClassLoader的使用詳解

    類加載器負(fù)責(zé)讀取Java字節(jié)代碼,并轉(zhuǎn)換成java.lang.Class類的一個實例的代碼模塊。本文主要和大家聊聊JVM類加載器ClassLoader的使用,需要的可以了解一下
    2022-12-12
  • Springboot配置文件內(nèi)容加密代碼實例

    Springboot配置文件內(nèi)容加密代碼實例

    這篇文章主要介紹了Springboot配置文件內(nèi)容加密代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Linux下啟動jar包的幾種常見方式

    Linux下啟動jar包的幾種常見方式

    最近在linux上發(fā)布了一個SpringBoot項目,研究了一下jar包在Linux上的集中啟動方式,這篇文章主要給大家介紹了Linux下啟動jar包的幾種常見方式,需要的朋友可以參考下
    2023-07-07
  • java多線程編程之使用thread類創(chuàng)建線程

    java多線程編程之使用thread類創(chuàng)建線程

    在Java中創(chuàng)建線程有兩種方法:使用Thread類和使用Runnable接口。在使用Runnable接口時需要建立一個Thread實例
    2014-01-01
  • 關(guān)于網(wǎng)頁報錯404原因以及解決方法

    關(guān)于網(wǎng)頁報錯404原因以及解決方法

    404錯誤是網(wǎng)站常見的錯誤之一,出現(xiàn)的原因很多,解決方法也有很多種,這篇文章主要給大家介紹了關(guān)于網(wǎng)頁報錯404原因以及解決方法的相關(guān)資料,需要的朋友可以參考下
    2024-01-01

最新評論