最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis Dynamic SQL 入門指南

 更新時間:2026年02月08日 09:48:03   作者:信碼由韁  
本文主要介紹了MyBatis Dynamic SQL 入門指南,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

MyBatis Dynamic SQL 是一種類型安全的 Java 領域特定語言(DSL),用于通過編程方式構建 SQL 查詢,而非編寫 SQL 字符串或基于 XML 的動態(tài)查詢。它在運行時使用流暢的 Java 構建器生成 SQL,同時仍通過標準的 MyBatis 映射器執(zhí)行。與手動拼接字符串或復雜的 XML 邏輯相比,這使得查詢構建更安全、更易于重構,并且更不容易出錯。

由于查詢是用 Java 編寫的,列名和表引用通過強類型的元數(shù)據(jù)類在編譯時進行驗證,這提供了更好的 IDE 支持并減少了運行時 SQL 錯誤。本文將解釋 MyBatis Dynamic SQL,并展示如何在 Java 應用程序中使用它。

1. 使用 MyBatis Dynamic SQL 可以做什么?

MyBatis Dynamic SQL 支持大多數(shù)常見的 SQL 操作,包括 SELECT、INSERTUPDATEDELETE,以及連接、子查詢、分頁、排序、條件過濾和批量操作。它允許我們逐步構建查詢,僅在某些參數(shù)存在時添加條件,這使其成為搜索界面和過濾 API 的理想選擇。

它直接與 MyBatis 映射器接口集成,意味著我們仍然可以受益于結果映射、事務處理和連接管理。由于它生成標準的 SQL,因此適用于 MyBatis 支持的任何數(shù)據(jù)庫,沒有供應商鎖定的問題。

1.1 MyBatis Dynamic SQL 的工作原理

Dynamic SQL 基于兩個組件:表元數(shù)據(jù)類和 DSL 構建器。元數(shù)據(jù)類用 Java 描述表和列。DSL 構建器使用這些類以流暢、類型安全的方式組裝 SQL 語句。

DSL 不直接執(zhí)行 SQL。相反,它生成語句提供者對象,例如 SelectStatementProviderInsertStatementProvider。這些對象被傳遞給使用 @SelectProvider、@InsertProvider 及類似注解標注的映射器方法,然后 MyBatis 使用其正常的執(zhí)行引擎來執(zhí)行這些語句。

2. 項目設置與依賴

Maven 依賴

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.15</version>
</dependency>
<dependency>
<groupId>org.mybatis.dynamic-sql</groupId>
<artifactId>mybatis-dynamic-sql</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.4.240</version>
<scope>runtime</scope>
</dependency>

這些依賴項包括 MyBatis 本身、Dynamic SQL DSL 以及一個用于測試的嵌入式數(shù)據(jù)庫。

注意

數(shù)據(jù)庫驅動可以替換為 MySQL、PostgreSQL 或任何其他支持的數(shù)據(jù)庫。MyBatis Dynamic SQL 不依賴于數(shù)據(jù)庫類型,僅依賴于標準 SQL 生成。

數(shù)據(jù)庫模式

schema.sql

CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
age INT
);
INSERT INTO users(username, email, age) VALUES
('thomas', 'thomas@jcg.com', 30),
('benjamin', 'benjamin@jcg.com', 22),
('charles', 'charles@jcg.com', 17);

此腳本創(chuàng)建一個簡單的表并插入測試數(shù)據(jù)。內存中的 H2 數(shù)據(jù)庫將在啟動時執(zhí)行此腳本,因此無需外部依賴即可測試查詢。

領域模型

public class User {
private Long id;
private String username;
private String email;
private Integer age;
// Getter 和 Setter 方法...
}

這個 POJO 代表數(shù)據(jù)庫中的一行。MyBatis 會自動使用匹配的字段名將列映射到字段,因此本例不需要額外的結果映射。

3. 用于 Dynamic SQL 的表元數(shù)據(jù)

下面的類以類型安全的方式定義數(shù)據(jù)庫表及其列,允許在構建查詢時被 Dynamic SQL DSL 引用。它充當 Java 代碼與實際數(shù)據(jù)庫結構之間的橋梁,實現(xiàn)了列名和類型的編譯時驗證。

public final class UserDynamicSqlSupport {
public static final User user = new User();
public static final SqlColumn<Long> id = user.id;
public static final SqlColumn<String> username = user.username;
public static final SqlColumn<String> email = user.email;
public static final SqlColumn<Integer> age = user.age;
public static final class User extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<String> username = column("username", JDBCType.VARCHAR);
public final SqlColumn<String> email = column("email", JDBCType.VARCHAR);
public final SqlColumn<Integer> age = column("age", JDBCType.INTEGER);
public User() {
super("users");
}
}
}

這個類為 users 表定義了類型安全的元數(shù)據(jù),使 MyBatis Dynamic SQL 可以在不使用原始 SQL 字符串的情況下構建查詢。DSL 使用這些 Java 對象而非按名稱引用列,從而提高了安全性和 IDE 支持。

內部類 User 繼承 SqlTable,這將其標記為可用于 from(user) 和連接等子句的數(shù)據(jù)表。構造函數(shù)調用 super("users") 來告知 MyBatis 要在 SQL 語句(如 FROM users)中呈現(xiàn)的確切表名。

每個列都使用 SqlTable 中的 column() 方法定義,該方法注冊列名及其 JDBC 類型。這會產(chǎn)生強類型的 SqlColumn<T> 對象,確保比較和條件在編譯時使用正確的 Java 類型。

外部類公開了對表及其列的靜態(tài)引用,以便于靜態(tài)導入,使得查詢讀起來很自然,例如:select(id, username).from(user),同時保持完全的類型安全和重構友好。

映射器接口

@Mapper
public interface UserMapper {
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
List<User> selectMany(SelectStatementProvider selectStatement);
}

@Mapper 注解告訴 MyBatis 此接口應注冊為映射器并在運行時進行代理。MyBatis 會自動生成實現(xiàn),因此不需要具體的類。

selectMany 方法接受一個 SelectStatementProvider,它封裝了完全呈現(xiàn)的 SQL 語句及其參數(shù)。MyBatis 執(zhí)行該語句并將每個結果行映射到 User 對象,將它們作為 List<User> 返回。

@SelectProvider 注解指定 SQL 將由 MyBatis Dynamic SQL 的一部分 SqlProviderAdapter 動態(tài)提供。實際的 SQL 是在運行時從使用 DSL 構建的 SelectStatementProvider 生成的,而不是在注解或 XML 中編寫 SQL。

4. 構建動態(tài)查詢

在這里,我們使用流暢的 Dynamic SQL DSL 構建 SQL 語句,而不是編寫原始 SQL 字符串。

public static void main(String[] args) throws Exception {
MyBatisUtil.runSchema();
try (SqlSession session = MyBatisUtil.getSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
SelectStatementProvider select
= select(id, username, email, age)
.from(user)
.where(age, isGreaterThan(18))
.and(username, isLike("%tho%"))
.orderBy(username)
.build()
.render(RenderingStrategies.MYBATIS3);
List<User> users = mapper.selectMany(select);
users.forEach(u
-> System.out.println(u.getUsername() + " - " + u.getAge()));
}
}

此代碼使用流暢的 Dynamic SQL DSL 動態(tài)構建一個 SELECT 查詢,并將其渲染為與 MyBatis 兼容的語句提供者。通過以編程方式添加條件,它能夠以類型安全且可維護的方式創(chuàng)建復雜的過濾器。在本例中,查詢選擇 age 大于 18 歲且 username 包含 "tho" 的用戶,然后按用戶名字母順序對結果進行排序。

MyBatis 工具類

public class MyBatisUtil {
private static SqlSessionFactory factory;
static {
try {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static SqlSession getSession() {
return factory.openSession(true);
}
public static void runSchema() throws IOException, SQLException {
try (SqlSession session = getSession()) {
Connection conn = session.getConnection();
Statement stmt = conn.createStatement();
try (InputStream is = Resources.getResourceAsStream("schema.sql")) {
String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
stmt.execute(sql);
}
}
}
}

此工具類加載 MyBatis 配置,構建 SqlSessionFactory,并提供對數(shù)據(jù)庫會話的訪問。它還通過執(zhí)行 SQL 腳本(schema.sql)手動初始化數(shù)據(jù)庫模式。

5. 使用 Dynamic SQL 進行插入、更新和刪除

MyBatis 中的 Dynamic SQL 允許我們使用流暢的 DSL 以編程方式構造 INSERT、UPDATE 和 DELETE 語句。在此,我們演示如何執(zhí)行這些常見的數(shù)據(jù)操作。

// INSERT
User newUser = new User();
newUser.setUsername("andrew");
newUser.setEmail("andrew@jcg.com");
newUser.setAge(28);
InsertStatementProvider<User> insert
= insert(newUser)
.into(user)
.map(username).toProperty("username")
.map(email).toProperty("email")
.map(age).toProperty("age")
.build()
.render(RenderingStrategies.MYBATIS3);
int inserted = mapper.insert(insert);
System.out.println("Rows inserted: " + inserted);
// UPDATE
UpdateStatementProvider update
= update(user)
.set(age).equalTo(35)
.where(username, isEqualTo("thomas"))
.build()
.render(RenderingStrategies.MYBATIS3);
int updated = mapper.update(update);
System.out.println("Rows updated: " + updated);
// DELETE
DeleteStatementProvider delete
= deleteFrom(user)
.where(age, isLessThan(18))
.build()
.render(RenderingStrategies.MYBATIS3);
int deleted = mapper.delete(delete);
System.out.println("Rows deleted: " + deleted);

相同的 DSL 風格也用于寫操作。語句以流暢的方式構建、渲染,然后由映射器提供者方法執(zhí)行。

  • INSERT:創(chuàng)建一個新的 User 對象并填充值。使用 Dynamic SQL DSL,我們將其字段映射到表列并生成 InsertStatementProvider。映射器執(zhí)行插入操作,返回受影響的行數(shù)。
  • UPDATE:DSL 構建一個更新語句,將用戶名為 "thomas" 的用戶的年齡設置為 35。這確保只修改目標行,映射器執(zhí)行更新。
  • DELETE:刪除語句移除所有年齡小于 18 歲的用戶。在 DSL 中使用條件保證了類型安全并避免了字符串拼接。

更新后的映射器接口

為了支持這些操作,映射器接口必須包含用于 INSERT、UPDATE 和 DELETE 的方法,使用 MyBatis Dynamic SQL 提供者。

// INSERT
@InsertProvider(type = SqlProviderAdapter.class, method = "insert")
int insert(InsertStatementProvider<User> insertStatement);
// UPDATE
@UpdateProvider(type = SqlProviderAdapter.class, method = "update")
int update(UpdateStatementProvider updateStatement);
// DELETE
@DeleteProvider(type = SqlProviderAdapter.class, method = "delete")
int delete(DeleteStatementProvider deleteStatement);

映射器中的每個方法處理一個特定的 DML 操作(插入、更新或刪除),并接受一個封裝了生成的 SQL 及其參數(shù)的 InsertStatementProvider、UpdateStatementProviderDeleteStatementProvider。這種方法允許所有寫操作都在 Java 中以編程方式表達,而無需手動組合 SQL 字符串,同時仍能利用 MyBatis 高效地執(zhí)行語句和映射結果。

6. 結論

在本文中,我們探討了如何在 Java 應用程序中使用 MyBatis Dynamic SQL 來創(chuàng)建類型安全、可維護且可編程的 SQL 查詢。通過將 SQL 構建與執(zhí)行分離,MyBatis Dynamic SQL 簡化了復雜查詢邏輯的處理,降低了錯誤風險,并提高了代碼可讀性。這種方法非常適合查詢需要動態(tài)變化或經(jīng)常修改的應用程序。

到此這篇關于MyBatis Dynamic SQL 入門指南的文章就介紹到這了,更多相關MyBatis Dynamic SQL內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • IDEA如何加載resources文件夾下文件相對路徑

    IDEA如何加載resources文件夾下文件相對路徑

    這篇文章主要介紹了IDEA如何加載resources文件夾下文件相對路徑問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • SpringBoot整合Lucene實現(xiàn)全文檢索的詳細步驟

    SpringBoot整合Lucene實現(xiàn)全文檢索的詳細步驟

    全文搜索(Full-Text?Search)是指對大規(guī)模存儲在計算機系統(tǒng)中的文本數(shù)據(jù)進行檢索和匹配的技術,它允許用戶輸入關鍵字,然后從海量的文本數(shù)據(jù)中快速找到相關的信息,本文介紹了SpringBoot整合Lucene實現(xiàn)全文檢索的詳細步驟,需要的朋友可以參考下
    2024-03-03
  • Java合并兩個及以上有序鏈表的示例詳解

    Java合并兩個及以上有序鏈表的示例詳解

    這篇文章主要通過兩個例題為大家介紹一下Java合并兩個及以上有序鏈表的實現(xiàn)方法,文中的示例代碼講解詳細,具有一定的學習價值,需要的可以參考一下
    2022-11-11
  • SpringBoot整合Keycloak的項目實踐

    SpringBoot整合Keycloak的項目實踐

    本文介紹了如何設置了Keycloak 服務器及在SpringBoot中使用 Spring Security OAuth2.0結合Keycloak實現(xiàn)認證和授權,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-01-01
  • idea更換jdk版本的完整步驟(附詳細圖文)

    idea更換jdk版本的完整步驟(附詳細圖文)

    idea很多地方都設置了jdk版本,不同模塊的jdk版本也可能不一樣,這篇文章主要介紹了idea更換jdk版本的完整步驟,通過文中介紹的步驟可以成功更換jdk版本,需要的朋友可以參考下
    2025-04-04
  • java中struts 框架的實現(xiàn)

    java中struts 框架的實現(xiàn)

    本文給大家介紹的是java中struts 框架的實現(xiàn),有需要的小伙伴可以參考下。
    2015-06-06
  • java正則表達式之Pattern與Matcher類詳解

    java正則表達式之Pattern與Matcher類詳解

    這篇文章主要給大家介紹了關于java正則表達式之Pattern與Matcher類的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型示例詳解

    Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型示例詳解

    這篇文章主要介紹了Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型,阻塞隊列的特點就是阻塞兩個字,阻塞功能使得生產(chǎn)者和消費者兩端的能力得以平衡,當有任何一端速度過快時,阻塞隊列便會把過快的速度降下來,感興趣的朋友可以參考下
    2023-12-12
  • Java面向對象編程之類的繼承詳解

    Java面向對象編程之類的繼承詳解

    這篇文章主要介紹了Java面向對象編程之類的繼承,結合實例形式較為詳細的分析了Java面向對象編程類的概念、功能、使用方法及相關注意事項,需要的朋友可以參考下
    2018-02-02
  • 使用Spring掃描Mybatis的mapper接口的三種配置

    使用Spring掃描Mybatis的mapper接口的三種配置

    這篇文章主要介紹了使用Spring掃描Mybatis的mapper接口的三種配置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論

临湘市| 景谷| 都匀市| 丹东市| 土默特右旗| 永平县| 瓮安县| 宣汉县| 海口市| 田东县| 嫩江县| 新绛县| 芦山县| 仙游县| 库伦旗| 开远市| 新宁县| 和平区| 安顺市| 阿巴嘎旗| 酉阳| 佛冈县| 山阴县| 舞钢市| 旬阳县| 会同县| 肥乡县| 荣昌县| 绥棱县| 钦州市| 张家港市| 耒阳市| 兖州市| 江都市| 荃湾区| 安仁县| 西城区| 乳山市| 易门县| 宁武县| 休宁县|