1. 程式人生 > 實用技巧 >Mybatis-plus學習筆記,基於springboot

Mybatis-plus學習筆記,基於springboot

1、依賴

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>

2、自動生成程式碼

public class CodeBuilder {
    public static void main(String[] args) {
        AutoGenerator autoGenerator = new AutoGenerator();

        // 資料庫表名
        String[] tableList = {
                ""
        };

        // 作者
        String author = "";
        // 資料庫樂觀鎖欄位名
        String version = "version";
        // 資料庫邏輯刪除欄位名
        String deleted = "deleted";
        // 資料庫表字首
        String tablePrefix = "";
        // 欄位字首
        String columnPrefix = "";
        // 包名
        String packageName = "";

        // JDBC
        String dataBaseUrl = "";
        String dataBaseDriverName = "";
        String dataBaseUsername = "";
        String dataBasePassword = "";

        // 自動填充配置
        // 根據自己的表結構修改
        // 建立時間
        TableFill createTime = new TableFill("f_create_time", FieldFill.INSERT);
        // 修改時間
        TableFill updateTime = new TableFill("f_update_time", FieldFill.INSERT_UPDATE);
        // 經辦人ID
        TableFill operatorId = new TableFill("f_operator_id", FieldFill.INSERT_UPDATE);
        // 經辦人名字
        TableFill operator = new TableFill("f_operator", FieldFill.INSERT_UPDATE);

        ArrayList<TableFill> list = new ArrayList<>();

        list.add(createTime);
        list.add(updateTime);
        list.add(operatorId);
        list.add(operator);

        // 全域性配置
        GlobalConfig globalConfig = new GlobalConfig();
        String path = System.getProperty("user.dir");
        globalConfig.setOutputDir(path + "/src/main/java");
        globalConfig.setAuthor(author);
        globalConfig.setOpen(false);
        globalConfig.setServiceName("%sService");
        globalConfig.setControllerName("%sController");
        globalConfig.setEntityName("%sPO");
        globalConfig.setMapperName("%sDao");
        globalConfig.setFileOverride(true);
        globalConfig.setBaseResultMap(true);
        globalConfig.setBaseColumnList(true);
        globalConfig.setActiveRecord(true);
        globalConfig.setSwagger2(true);
        globalConfig.setIdType(IdType.AUTO);
        globalConfig.setDateType(DateType.ONLY_DATE);
        autoGenerator.setGlobalConfig(globalConfig);

        // 資料來源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl(dataBaseUrl);
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setDriverName(dataBaseDriverName);
        dataSourceConfig.setUsername(dataBaseUsername);
        dataSourceConfig.setPassword(dataBasePassword);
        autoGenerator.setDataSource(dataSourceConfig);

        // 包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setMapper("dao");
        packageConfig.setController("controller");
        packageConfig.setEntity("entity.po");
        packageConfig.setService("service");
        packageConfig.setParent(packageName);
        autoGenerator.setPackageInfo(packageConfig);

        // 策略設定
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude(tableList);
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setEntitySerialVersionUID(false);
        strategy.setEntityTableFieldAnnotationEnable(true);
        strategy.setVersionFieldName(version);
        strategy.setLogicDeleteFieldName(deleted);
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityColumnConstant(true);
        strategy.setChainModel(true);
        strategy.setTablePrefix(tablePrefix);
        strategy.setFieldPrefix(columnPrefix);


        strategy.setTableFillList(list);

        // RestFull 風格
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);

        autoGenerator.setStrategy(strategy);

        autoGenerator.execute();

    }


}

3、springboot註解新增mapperscan

@MapperScan("com.hong.mapper")//可以寫在MybatisplusConfig中

4、註解

@TableName

  • 表名註解

    屬性 型別 必須指定 預設值 描述
    value String "" 表名
    schema String "" schema
    keepGlobalPrefix boolean false 是否保持使用全域性的 tablePrefix 的值(如果設定了全域性 tablePrefix 且自行設定了 value 的值)
    resultMap String "" xml 中 resultMap 的 id
    autoResultMap boolean false 是否自動構建 resultMap 並使用(如果設定 resultMap 則不會進行 resultMap 的自動構建並注入)

@TableId

  • 主鍵註解

    屬性 型別 必須指定 預設值 描述
    value String "" 主鍵欄位名
    type Enum IdType.NONE 主鍵型別
  • IdType

    描述
    AUTO 資料庫ID自增
    NONE 無狀態,該型別為未設定主鍵型別(註解裡等於跟隨全域性,全局裡約等於 INPUT)
    INPUT insert前自行set主鍵值
    ASSIGN_ID 分配ID(主鍵型別為Number(Long和Integer)或String)(since 3.3.0),使用介面IdentifierGenerator的方法nextId(預設實現類為DefaultIdentifierGenerator雪花演算法)

@TableField

  • 欄位註解

    屬性 型別 必須指定 預設值 描述
    value String "" 資料庫欄位名
    el String "" 對映為原生 #{ ... } 邏輯,相當於寫在 xml 裡的 #{ ... } 部分
    exist boolean true 是否為資料庫表字段
    condition String "" 欄位 where 實體查詢比較條件,有值設定則按設定的值為準,沒有則為預設全域性的 %s=#{%s},參考
    update String "" 欄位 update set 部分注入, 例如:update="%s+1":表示更新時會set version=version+1(該屬性優先順序高於 el 屬性)
    insertStrategy Enum N DEFAULT 舉例:NOT_NULL: insert into table_a(column) values (#{columnProperty})
    updateStrategy Enum N DEFAULT 舉例:IGNORED: update table_a set column=#{columnProperty}
    whereStrategy Enum N DEFAULT 舉例:NOT_EMPTY: where column=#{columnProperty}
    fill Enum FieldFill.DEFAULT 欄位自動填充策略
    select boolean true 是否進行 select 查詢
    keepGlobalFormat boolean false 是否保持使用全域性的 format 進行處理
    jdbcType JdbcType JdbcType.UNDEFINED JDBC型別 (該預設值不代表會按照該值生效)
    typeHandler Class<? extends TypeHandler> UnknownTypeHandler.class 型別處理器 (該預設值不代表會按照該值生效)
    numericScale String "" 指定小數點後保留的位數

@Version

  • 樂觀鎖

@TableLogic

  • 邏輯刪除註解

    屬性 型別 必須指定 預設值 描述
    value String "" 邏輯未刪除值
    delval String "" 邏輯刪除值

5、配置外掛

1、日誌(控制檯輸出)

#配置日誌輸出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

2、自動填充策略

  • 資料庫新增對應欄位

    • create_time

    • update_time

    • datatime 型別

  • 對應屬性需要加上註解

        @TableField(fill = FieldFill.INSERT)
        private Date creatTime;
    
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Date updateTime;
    
  • 編寫MybatisPlusConfig類

    @Configuration
    public class MybatisPlusConfig {
    
    
        /**
         * 註冊欄位自動填充
         *
         * @return
         */
        @Bean
        public MetaObjectHandler getMetaObjectHandler() {
    
            return new MetaObjectHandler() {
                @Override
                public void insertFill(MetaObject metaObject) {
                    this.setFieldValByName("createTime", new Date(), metaObject);
                    this.setFieldValByName("updateTime", new Date(), metaObject);
    
    
                }
    
                @Override
                public void updateFill(MetaObject metaObject) {
                    this.setFieldValByName("updateTime", new Date(), metaObject);
                }
            };
        }
    
        /**
         * 樂觀鎖外掛
         *
         * @return
         */
        @Bean
        public OptimisticLockerInterceptor getOptimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    
        /**
         * 分頁外掛
         *
         * @return
         */
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            return new PaginationInterceptor();
        }
    
    }
    
    

3、樂觀鎖version

  • 資料庫新增對應欄位,預設值為1

    • version
  • 實體類新增對應註解

        @Version
        private Integer version;
    

4、邏輯刪除

  • 解釋:在邏輯上實現刪除,實際上資料庫沒有被刪除,但是普通使用者查詢不到,只有管理員能查詢

  • 在資料庫新增對應欄位,預設0為沒有刪除,1為邏輯刪除

    • deleted
  • 實體類中新增對應註解

        @TableLogic
        private Integer deleted;
    

5、分頁

  • 查詢測試

        @Test
        void selectPageTest() {
            //引數一:當前頁
            //引數二:頁面大小
            Page<TUser> objectPage = new Page<>(1,2);
            tUserMapper.selectPage(objectPage,null);
            objectPage.getRecords().forEach(System.out::println);
        }
    

6、效能分析外掛(P6spy)

  • 匯入依賴

    <dependency>
        <groupId>p6spy</groupId>
        <artifactId>p6spy</artifactId>
        <version>3.9.0</version>
    </dependency>
    
  • 接著編輯 application.properties 檔案,更換資料庫連線驅動:

    #資料庫資訊配置
    spring.datasource.username=
    spring.datasource.password=
    spring.datasource.url=jdbc:p6spy:mysql:
    spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
    
  • 最後建立 spy.properties 配置檔案即可

    #3.2.1以上使用
    modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
    # 自定義日誌列印
    logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
    #日誌輸出到控制檯
    appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
    # 使用日誌系統記錄 sql
    #appender=com.p6spy.engine.spy.appender.Slf4JLogger
    # 設定 p6spy driver 代理
    deregisterdrivers=true
    # 取消JDBC URL字首
    useprefix=true
    # 配置記錄 Log 例外,可去掉的結果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
    excludecategories=info,debug,result,commit,resultset
    # 日期格式
    dateformat=yyyy-MM-dd HH:mm:ss
    # 實際驅動可多個
    #driverlist=org.h2.Driver
    # 是否開啟慢SQL記錄
    outagedetection=true
    # 慢SQL記錄標準 2 秒
    outagedetectioninterval=2
    

7、多資料來源

  • 匯入依賴
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>3.2.0</version>
</dependency>
  • 資料來源配置檔案
spring:
  datasource:
    dynamic:
      primary: master #設定預設的資料來源或者資料來源組,預設值即為master
      strict: false #設定嚴格模式,預設false不啟動. 啟動後在未匹配到指定資料來源時候會丟擲異常,不啟動則使用預設資料來源.
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0開始支援SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx) # 內建加密,使用請檢視詳細文件
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
          schema: db/schema.sql # 配置則生效,自動初始化表結構
          data: db/data.sql # 配置則生效,自動初始化資料
          continue-on-error: true # 預設true,初始化失敗是否繼續
          separator: ";" # sql預設分號分隔符
          
       #......省略
       #以上會配置一個預設庫master,一個組slave下有兩個子庫slave_1,slave_2
  • 使用@DS註解切換資料來源
@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  
  @Override
  @DS("slave_1")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}

6、CRUD(service層)

save

// 插入一條記錄(選擇欄位,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

remove

// 根據 entity 條件,刪除記錄
boolean remove(Wrapper<T> queryWrapper);
// 根據 ID 刪除
boolean removeById(Serializable id);
// 根據 columnMap 條件,刪除記錄
boolean removeByMap(Map<String, Object> columnMap);
// 刪除(根據ID 批量刪除)
boolean removeByIds(Collection<? extends Serializable> idList);

update

// 根據 UpdateWrapper 條件,更新記錄 需要設定sqlset
boolean update(Wrapper<T> updateWrapper);
// 根據 whereEntity 條件,更新記錄
boolean update(T entity, Wrapper<T> updateWrapper);
// 根據 ID 選擇修改
boolean updateById(T entity);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

get

// 根據 ID 查詢
T getById(Serializable id);
// 根據 Wrapper,查詢一條記錄。結果集,如果是多個會丟擲異常,隨機取一條加上限制條件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根據 Wrapper,查詢一條記錄
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根據 Wrapper,查詢一條記錄
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根據 Wrapper,查詢一條記錄
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);