MyBatis-Plus條件構造器:構建安全、高效的資料庫查詢

ccm03發表於2024-11-04

一、關於條件構造器(Wrapper)

1.1 簡介

MyBatis-Plus 提供了一套強大的條件構造器(Wrapper),用於構建複雜的資料庫查詢條件。Wrapper 類允許開發者以鏈式呼叫的方式構造查詢條件,無需編寫繁瑣的 SQL 語句,從而提高開發效率並減少 SQL 注入的風險。

edae4c45-b7c2-4e1c-a975-ff823dacb29c

1.2 發展

  1. 核心功能的發展

    • 從早期的MyBatis-Plus版本開始,條件構造器(Wrapper)就已經作為核心功能之一,用於構建複雜的資料庫查詢條件。隨著版本的迭代,條件構造器的功能不斷增強,提供了更多的方法來支援各種查詢操作,如eq​(等於)、ne​(不等於)、gt​(大於)、lt​(小於)等。
  2. 鏈式呼叫的最佳化

    • 條件構造器支援鏈式呼叫,這使得程式碼更加簡潔和易讀。隨著MyBatis-Plus的發展,鏈式呼叫的流暢性和易用性得到了進一步的最佳化,使得開發者可以更加方便地構建複雜的查詢條件。
  3. Lambda表示式的引入

    • 隨著Java 8的普及,MyBatis-Plus引入了基於Lambda表示式的條件構造器,如LambdaQueryWrapper​和LambdaUpdateWrapper​,這使得開發者可以使用更加現代的程式設計方式來構建查詢和更新條件,提高了程式碼的可讀性和安全性。
  4. 功能擴充套件

    • MyBatis-Plus條件構造器的功能不斷擴充套件,新增了許多方法,如eqSql​、gtSql​、geSql​、ltSql​、leSql​等,這些方法允許開發者直接在條件構造器中嵌入SQL片段,提供了更高的靈活性。
  5. 效能最佳化

    • 隨著MyBatis-Plus的發展,條件構造器在效能上也得到了最佳化。透過減少不必要的SQL拼接和最佳化條件構造邏輯,提高了查詢的效率。
  6. 易用性的提升

    • MyBatis-Plus不斷改進條件構造器的易用性,例如透過提供更多的方法來支援不同的查詢場景,如groupBy​、orderBy​、having​等,使得開發者可以更加方便地構建複雜的查詢條件。

1.3 特點

MyBatis-Plus的條件構造器具有以下特點:

  1. 鏈式呼叫:Wrapper類允許開發者以鏈式呼叫的方式構造查詢條件,無需編寫繁瑣的SQL語句,從而提高開發效率。
  2. 安全性:透過使用Wrapper,可以避免直接拼接SQL片段,減少SQL隱碼攻擊的風險。
  3. 靈活性:支援多種查詢操作,如等於、不等於、大於、小於等,以及邏輯組合如and​和or​。
  4. Lambda表示式:LambdaQueryWrapper和LambdaUpdateWrapper透過Lambda表示式引用實體類的屬性,避免了硬編碼欄位名,提高了程式碼的可讀性和可維護性。
  5. 減少程式碼量:Wrappers類作為一個靜態工廠類,可以快速建立Wrapper例項,減少程式碼量,提高開發效率。
  6. 執行緒安全性:Wrapper例項不是執行緒安全的,建議每次使用時建立新的Wrapper例項,以避免多執行緒環境下的資料競爭和潛在錯誤。
  7. 支援複雜查詢:支援巢狀查詢和自定義SQL片段,透過nested​和apply​方法,可以構建更復雜的查詢條件。
  8. 型別處理器:在Wrapper中可以使用TypeHandler處理特殊的資料型別,增強了對資料庫型別的支援。
  9. 更新操作簡化:使用UpdateWrapper或LambdaUpdateWrapper時,可以省略實體物件,直接在Wrapper中設定更新欄位。

1.4 主要型別

MyBatis-Plus 提供了多種條件構造器,以滿足不同的查詢需求:

  1. QueryWrapper<T> :用於構建查詢條件,支援鏈式呼叫,可以非常方便地新增各種查詢條件。
  2. UpdateWrapper<T> :用於構建更新條件,支援鏈式呼叫,可以方便地新增各種更新條件。
  3. LambdaQueryWrapper<T> :使用 Lambda 表示式來構建查詢條件,避免了欄位名錯誤的問題,增強了程式碼的可讀性和健壯性。
  4. LambdaUpdateWrapper<T> :使用 Lambda 表示式來構建更新條件,同樣可以避免欄位名錯誤的問題。
  5. AbstractWrapper<T> :是一個抽象類,其他 Wrapper 類繼承自這個類,提供了一些基礎的方法實現。

1e12f7c4-aa70-4024-bbbc-f820a4772f8c

二、基本運用

2.1 使用方法

條件構造器允許開發者以鏈式呼叫的方式構造SQL的WHERE子句,提供了極大的靈活性和便利性。例如,使用QueryWrapper可以這樣構建查詢條件:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "Kimi").lt("age", 30);

這將生成SQL:SELECT * FROM user WHERE name = 'Kimi' AND age < 30​。

2.2 示例

QueryWrapper 示例

// 建立 QueryWrapper 物件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();

// 新增查詢條件
queryWrapper.eq("name", "張三") // 欄位等於某個值
            .gt("age", 18)      // 欄位大於某個值
            .like("email", "%@gmail.com"); // 欄位包含某個值

// 使用條件進行查詢
List<User> users = userMapper.selectList(queryWrapper);

UpdateWrapper 示例

// 建立 UpdateWrapper 物件
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();

// 設定更新條件
updateWrapper.eq("id", 1); // 更新 id=1 的記錄

// 設定要更新的資料
User user = new User();
user.setName("李四");
user.setAge(20);

// 執行更新操作
int result = userMapper.update(user, updateWrapper);

LambdaQueryWrapper 示例

// 建立 LambdaQueryWrapper 物件
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

// 新增查詢條件
lambdaQueryWrapper.eq(User::getName, "張三")
                  .gt(User::getAge, 18)
                  .like(User::getEmail, "%@gmail.com");

// 使用條件進行查詢
List<User> users = userMapper.selectList(lambdaQueryWrapper);

三、Wrapper 類

3.1 簡介

在 MyBatis-Plus 中,Wrapper 類是構建查詢和更新條件的核心工具。

image

image

3.2 方法

MyBatis-Plus的Wrapper類提供了一系列方法來構建複雜的資料庫查詢條件。以下是一些常用的Wrapper類方法彙總:

  1. 基本條件方法

    • eq​:等於條件,例如 wrapper.eq("name", "zhangsan")​。
    • ne​:不等於條件,例如 wrapper.ne("name", "zhangsan")​。
    • gt​:大於條件,例如 wrapper.gt("age", 18)​。
    • lt​:小於條件,例如 wrapper.lt("age", 18)​。
    • ge​:大於等於條件,例如 wrapper.ge("age", 18)​。
    • le​:小於等於條件,例如 wrapper.le("age", 18)​。
    • between​:介於兩個值之間,例如 wrapper.between("age", 18, 30)​。
    • notBetween​:不介於兩個值之間,例如 wrapper.notBetween("age", 18, 30)​。
    • like​:模糊匹配,例如 wrapper.like("name", "%zhangsan%")​。
    • notLike​:不模糊匹配,例如 wrapper.notLike("name", "%zhangsan%")​。
    • likeLeft​:左模糊匹配,例如 wrapper.likeLeft("name", "zhangsan%")​。
    • likeRight​:右模糊匹配,例如 wrapper.likeRight("name", "%zhangsan")​。
    • isNull​:欄位值為null,例如 wrapper.isNull("name")​。
    • isNotNull​:欄位值不為null,例如 wrapper.isNotNull("name")​。
    • in​:欄位值在指定集合中,例如 wrapper.in("name", "zhangsan", "Tom")​。
    • notIn​:欄位值不在指定集合中,例如 wrapper.notIn("name", "zhangsan", "Tom")​。
  2. 邏輯組合方法

    • and​:新增一個AND條件,例如 wrapper.and(wq -> wq.eq("name", "zhangsan"))​。
    • or​:新增一個OR條件,例如 wrapper.or(wq -> wq.eq("name", "zhangsan"))​。
  3. SQL片段方法

    • apply​:新增自定義SQL片段,例如 wrapper.apply("name = {0}", "zhangsan")​。
    • last​:新增自定義SQL片段到末尾,例如 wrapper.last("order by name")​。
  4. 子查詢方法

    • inSql​:子查詢IN條件,例如 wrapper.inSql("name", "select name from user where age > 21")​。
    • notInSql​:子查詢NOT IN條件,例如 wrapper.notInSql("name", "select name from user where age > 21")​。
  5. 分組與排序方法

    • groupBy​:分組,例如 wrapper.groupBy("name")​。
    • orderByAsc​:升序排序,例如 wrapper.orderByAsc("age")​。
    • orderByDesc​:降序排序,例如 wrapper.orderByDesc("age")​。
  6. 其他方法

    • exists​:存在條件,例如 wrapper.exists("select * from user where name = {0}", "zhangsan")​。

    • notExists​:不存在條件,例如 wrapper.notExists("select * from user where name = {0}", "zhangsan")​。

    • set​:更新操作時設定欄位值,例如 updateWrapper.set("name", "zhangsan")​。

    • having(String column, Object val): HAVING 過濾條件,用於聚合後的過濾,例如

      queryWrapper.select("name", "age")
                          .groupBy("age")
                          .having("count(id) > 1");
      

以上方法提供了構建查詢和更新條件的靈活性和強大功能,使得MyBatis-Plus在資料庫操作方面更加高效和安全。

相關文章