MyBatis 使用的注意事項

1. MyBatis 中#{}和${}的區別

  • #{}: 解析爲一個 JDBC 預編譯語句(PreparedStatement )的參數標記符,一個 #{ } 代表一個佔位符 ,可預防大部分 SQL 注入
  • ${}: 純粹的 String 拼接,在動態 SQL 解析階段將會進行變量替換,當需要傳入表名或者按照列排序時可使用

2. MyBatis-plus 的字段非 null 更新

使用 Mapper 通過 bean 對象更新數據庫記錄的時候,字段更新的策略會影響更新的結果,mybatis-plus的字段默認策略是 FieldStrategy.NOT_NULL。該特性可在數據庫表映射生成的 bean 的屬性上通過以下註解使用

@TableField(value = "FstrLoanOrder",updateStrategy = FieldStrategy.NOT_EMPTY)
private String loanOrder;
public class GlobalConfig implements Serializable {

       ......
       /**
         * 字段驗證策略之 insert
         *
         * @since 3.1.2
         */
        private FieldStrategy insertStrategy = FieldStrategy.NOT_NULL;
        /**
         * 字段驗證策略之 update
         *
         * @since 3.1.2
         */
        private FieldStrategy updateStrategy = FieldStrategy.NOT_NULL;
        /**
         * 字段驗證策略之 select
         *
         * @since 3.1.2
         */
        private FieldStrategy selectStrategy = FieldStrategy.NOT_NULL;
    }
}
public enum FieldStrategy {
    /**
     * 忽略判斷
     */
    IGNORED,
    /**
     * 非NULL判斷, bean 對象屬性爲 NULL 則不更新對應表字段
     */
    NOT_NULL,
    /**
     * 非空判斷(只對字符串類型字段,其他類型字段依然爲非NULL判斷)
     */
    NOT_EMPTY,
    /**
     * 默認的,一般只用於註解裏
     * <p>1. 在全局裏代表 NOT_NULL</p>
     * <p>2. 在註解裏代表 跟隨全局</p>
     */
    DEFAULT,
    /**
     * 不加入 SQL
     */
    NEVER
}

3. MyBatis-plus 使用技巧

3.1 自定義 sql 使用條件構造器作爲參數

MyBatis-plus 中使用 @Select 等註解自定義了部分 SQL 語句,同時想使用其條件構造器時,只需要將構造器入參用@Param(Constants.WRAPPER)修飾,再在自定義語句中添加 ${ew.customSqlSegment} 佔位即可

 @Select("select FuiQuota from fund.t_fund_quota ${ew.customSqlSegment}")
 Long queryQuota(@Param(Constants.WRAPPER) LambdaQueryWrapper<FundQuota> queryWrapper);

3.2 inSql 子查詢

通常在代碼中都是簡單查詢,但是在完成某些比較奇葩的需求時可能需要用到嵌套子查詢,MyBatis-plus 爲此在查詢構造器中提供了 inSql()方法

 LambdaQueryWrapper<Request> wrapper = Wrappers.<MatchRequest>lambdaQuery().inSql(Request::getId, insql)

3.3 and / or / nested 語句嵌套

有些複雜的查詢會用到嵌套語句,也就是包裹在括號中的語句,來表示一種條件的並列。這種場景需要動態拼接 SQL 語句,一個示例如下:OR 嵌套中存在兩個 AND 連接的條件,可表示語句 OR (FuiProductId = ? AND FuiTradeId IN (?, ?))。如果 or() 方法不傳入任何參數,則屬於外層普通的 OR 連接符號

wrapper.or(orWrapper -> {
    orWrapper.eq(Target::getProductId, item.getProductId());
    if (!CollectionUtils.isEmpty(item.getTradeIds())) {
        orWrapper.in(Target::getTradeId, item.getTradeIds());
    }
}

3.4 讀寫分離

整合 dynamic-datasource-spring-boot-starter 可以方便地使用 @DS 註解實現數據源切換,寫入時在Mapper方法上使用@DS("master")切換主庫,讀取則使用@DS("slave")切換從庫即可

spring:
  datasource:
    dynamic:
      # 默認的數據源或者數據源組
      primary: master 
      datasource:
      # 主庫名稱 master
        master:
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          # 重點配置,主庫所在服務器 url
          url: jdbc:mysql://xx.xx.xx.xx:3306/request?characterEncoding=utf8&useSSL=false
          druid: # 以下參數針對每個庫可以重新設置druid參數
            initial-size:
            validation-query: select 1 FROM DUAL #比如oracle就需要重新設置這個
        # 從庫名稱 slave
        slave:
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          # 重點配置,從庫所在服務器 url
          url: jdbc:mysql://xx.xx.xx.xx:3306/request?characterEncoding=utf8&useSSL=false
          druid: # 以下參數針對每個庫可以重新設置druid參數
            initial-size:
            validation-query: select 1 FROM DUAL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章