MyBatis?Plus?導(dǎo)入IdType失敗的解決
MyBatis Plus 導(dǎo)入IdType失敗
import com.baomidou.mybatisplus.annotation.IdType;
修正Entity模板IdType引入包名到
com.baomidou.mybatisplus.enums.IdType
所以修改為
import com.baomidou.mybatisplus.enums.IdType
既可
MybatisPlus學(xué)習(xí)筆記
一、MybatisPlus概述
1.MyBatisPlus可以節(jié)省我們大量工作時間,所有的CRUD代碼它都可以自動化完成!
官網(wǎng):https://mp.baomidou.com/ MyBatis Plus,簡化 MyBatis
2.特性
- 無侵入:只做增強(qiáng)不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般順滑
- 損耗?。簡蛹磿詣幼⑷牖?CURD,性能基本無損耗,直接面向?qū)ο蟛僮鳎?BaseMapper
- 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service,僅僅通過少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求, 以后簡單的CRUD操作,它不用自己編寫 了!
- 支持 Lambda 形式調(diào)用:通過 Lambda 表達(dá)式,方便的編寫各類查詢條件,無需再擔(dān)心字段寫錯
- 支持主鍵自動生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 -Sequence),可自由配 置,完美解決主鍵問題 支持
- ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用,實(shí)體類只需繼承 Model 類即可進(jìn)行強(qiáng)大 的 CRUD 操作
- 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用(自動幫你生成代碼)
- 內(nèi)置分頁插件:基于 MyBatis 物理分頁,開發(fā)者無需關(guān)心具體操作,配置好插件之后,寫分頁等同于普通 List 查詢
- 分頁插件支持多種數(shù)據(jù)庫:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、 Postgre、SQLServer 等多種數(shù)據(jù)庫
- 內(nèi)置性能分析插件:可輸出 Sql 語句以及其執(zhí)行時間,建議開發(fā)測試時啟用該功能,能快速揪出慢查詢
- 內(nèi)置全局?jǐn)r截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤 操作
二、快速入門
快速開始 | MyBatis-Plus (baomidou.com)
1.創(chuàng)建數(shù)據(jù)庫
2.創(chuàng)建user表
3.創(chuàng)建springboot項(xiàng)目
4.導(dǎo)入相關(guān)依賴
<!--數(shù)據(jù)庫驅(qū)動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--Lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mybatis-plus--> <!-- mybatis-plus 是自己開發(fā),并非官方的! --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency>
盡量不要同時導(dǎo)入mybatis和mybatis-plus,可能會出現(xiàn)問題
5.連接數(shù)據(jù)庫
# 連接數(shù)據(jù)庫(mysql 8) spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # useSSL:是否使用安全連接 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
6.傳統(tǒng)步驟:pojo–>dao(CRUD操作,配置mapper文件)–>service–>controller
6.使用mybatis-plus
pojo
package edu.ayit.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private int age; private String email; }
mapper接口
package edu.ayit.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import edu.ayit.pojo.User; import org.springframework.stereotype.Repository; //對應(yīng)mapper類繼承基本類 BaseMapper,泛型是對應(yīng)的實(shí)體類類型 @Repository public interface UserMapper extends BaseMapper<User> { //所有的CRUD操作編寫完成 }
要想主啟動類掃描到mapper包下的接口,需要在主啟動類上加上@MapperScan("edu.ayit.mapper")
使用
package edu.ayit; import edu.ayit.mapper.UserMapper; import edu.ayit.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest class MybatisPlusApplicationTests { @Autowired //所有方法都來自父類BaseMapper private UserMapper userMapper; @Test void contextLoads() { // 參數(shù)是一個Wrapper,條件構(gòu)造器,這里先不寫 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } }
三、配置日志
sql語句不可見,借助日志可見
# 配置日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
四、CRUD擴(kuò)展
1.Insert
@Test void testInsert(){ User user = new User(); user.setName("張三"); user.setAge(15); user.setEmail("123@qq.com"); int n = userMapper.insert(user); System.out.println(user); }
id沒有設(shè)置,自動生成
ID生成
@Data @AllArgsConstructor @NoArgsConstructor public class User { /** * public enum IdType { * AUTO(0),自增,數(shù)據(jù)庫也要設(shè)置自增 * NONE(1),未設(shè)置主鍵 * INPUT(2),手動輸入 * ID_WORKER(3),默認(rèn)的全局唯一id * UUID(4),全局唯一 uuid * ID_WORKER_STR(5);從ID_WORKER(3)中截取字符串作為主鍵 */ @TableId(type = IdType.AUTO) private Long id; private String name; private int age; private String email; }
2.Update
@Test void update(){ User user = new User(); user.setId(5L); user.setName("李四"); user.setAge(12); //根據(jù)Id更新數(shù)據(jù)庫,但參數(shù)是實(shí)體類對象 userMapper.updateById(user);
根據(jù)參數(shù)自動拼接動態(tài)sql
3.自動填充
數(shù)據(jù)的創(chuàng)建時間和修改時間等,這些操作應(yīng)該由數(shù)據(jù)庫自動完成。
阿里巴巴開發(fā)手冊規(guī)定:所有數(shù)據(jù)庫表都要有g(shù)mt_create和gmt_modified兩個字段,而且需要自動化。
方式一:數(shù)據(jù)庫表級別(不推薦)
1.在表中新增字段create_time和update_time,并設(shè)置數(shù)據(jù)類型和默認(rèn)值
2.修改實(shí)體類
@TableId(type = IdType.AUTO) private Long id; private String name; private int age; private String email; private Date createTime; private Date updateTime;
方式二:
1.清除數(shù)據(jù)庫默認(rèn)值
2.給實(shí)體類對應(yīng)屬性增加注解
@TableId(type = IdType.AUTO) private Long id; private String name; private int age; private String email; @TableField(fill = FieldFill.INSERT)//該字段在插入操作時填充 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE)//該字段在插入和更新操作時填充 private Date updateTime;
3.編寫處理器,處理注解
package edu.ayit.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; @Component public class MyMetaObjectHandler implements 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); } }
4.測試插入
5.測試更新
4.樂觀鎖
1.概念
樂觀鎖 :顧名思義,十分樂觀,它總是認(rèn)為不會出現(xiàn)問題,無論干什么不去上鎖!如果出現(xiàn)了問題, 再次更新值測試
悲觀鎖:十分悲觀,它總是認(rèn)為會出現(xiàn)問題,無論干什么都會上鎖!再去操作!
2.樂觀鎖實(shí)現(xiàn)方式
- 取出記錄時,獲取當(dāng)前version
- 更新時,帶上這個version
- 執(zhí)行更新時, set version = newVersion where version = oldVersion
- 如果version不對,就更新失敗
樂觀鎖:先查詢,獲取版本號 version = 1 --線程1 update mybatis-plus set name = "zhangsan" ,version = version+1 where id = 1 and version = 1; --線程2 搶先完成,完成后version = 2,會導(dǎo)致線程1執(zhí)行失敗 update mybatis-plus set name = "zhangsan" ,version = version+1 where id = 1 and version = 1;
3.測試樂觀鎖
- 給數(shù)據(jù)庫加上version字段
- 修改實(shí)體類代碼
@TableId(type = IdType.AUTO) private Long id; private String name; private int age; private String email; @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; @Version//樂觀鎖 private int version;
注冊組件
package edu.ayit.config; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; //可以將springboot主啟動類上的@MapperScan("edu.ayit.mapper")移到這里 @Configuration public class MybatisPlusConfig { //注冊樂觀鎖插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
5.查詢操作
//查詢?nèi)? @Test void contextLoads() { // 參數(shù)是一個Wrapper,條件構(gòu)造器,這里先不寫 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); /* for (User user : users) { System.out.println(user); }*/ } //測試查詢 @Test public void testSelectById(){ User user = userMapper.selectById(2L); System.out.println(user); } //測試批量查詢 @Test public void testSelectByBatchId(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L)); users.forEach(System.out::println); } //按條件查詢方法一:map操作 @Test void testSelectByCondition(){ Map map = new HashMap<String,Object>(); map.put("name","Tom"); map.put("age",28); List list = userMapper.selectByMap(map); list.forEach(System.out::println); }
6.分頁查詢
常見的分頁方式:
- 原始的limit分頁
- pageHelper第三方插件
- mybatis-plus也內(nèi)置了第三方插件
內(nèi)置插件如何使用?
1.配置攔截器組件(官網(wǎng)上有)
//注冊分頁插件 @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); return paginationInterceptor; }
2.直接使用page對象
//測試分頁 @Test void testSelectByPage(){ //參數(shù)1:當(dāng)前頁 參數(shù)2:每頁顯示條數(shù) Page<User> page = new Page<>(1,5); userMapper.selectPage(page, null); //獲取該頁所有記錄 page.getRecords().forEach(System.out::println); //獲取總數(shù)據(jù)條數(shù) System.out.println(page.getTotal()); }
3.查詢結(jié)果
7.刪除操作
基本刪除操作
//測試刪除 @Test void testDelete(){ //根據(jù)id刪除 userMapper.deleteById(1385852899430592517L); //根據(jù)id批次刪除 userMapper.deleteBatchIds(Arrays.asList(1385852899430592518L,1385852899430592519L,1385852899430592520L)); //根據(jù)條件刪除 HashMap<String, Object> map = new HashMap<>(); map.put("id",1385852899430592521L); userMapper.deleteByMap(map); }
8.邏輯刪除
物理刪除:從數(shù)據(jù)庫中直接移除
邏輯刪除:沒有從數(shù)據(jù)庫中移除,而是通過一個字段讓它失效,如 deleted = 0 變成 deleted = 1
管理員可以查看被用戶刪除的記錄,防止數(shù)據(jù)丟失,類似于回收站
測試
1.在數(shù)據(jù)庫中增加一個deleted字段
2.增加實(shí)體類屬性
@TableId(type = IdType.AUTO) private Long id; private String name; private int age; private String email; @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; @Version//樂觀鎖 private int version; @TableLogic//邏輯刪除 private int deleted;
3.配置邏輯刪除組件
//邏輯刪除組件 @Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); }
4.修改配置文件application.properties
# 配置邏輯刪除 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
5.測試邏輯刪除
//測試邏輯刪除 @Test void testLogicDelete(){ userMapper.deleteById(1L); }
查詢刪除記錄
查詢不到,但記錄沒被刪除,只是deleted字段的值被改變了,所以查詢不到。
9.性能分析插件(新版本無)
作用
用于查找運(yùn)行慢的sql。當(dāng)某條sql語句超過設(shè)定時間,程序會停止運(yùn)行。
測試
1.配置性能分析插件
/** * SQL執(zhí)行效率插件 */ @Bean @Profile({"dev","test"})// 設(shè)置 dev test 環(huán)境開啟,保證我們的效率 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setMaxTime(100); // ms設(shè)置sql執(zhí)行的最大時間,如果超過了則不 執(zhí)行 performanceInterceptor.setFormat(true); // 是否格式化代碼 return performanceInterceptor; }
2.要在SpringBoot中配置環(huán)境為dev或者 test 環(huán)境!
spring.profiles.active=dev
五、條件構(gòu)造器
官網(wǎng)資料:條件構(gòu)造器 | MyBatis-Plus (baomidou.com)
測試
1.查詢姓名不為空,郵箱不為空,年齡大于20歲的用戶
@Autowired //所有方法都來自父類BaseMapper private UserMapper userMapper; @Test void contextLoads() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //查詢姓名不為空,郵箱不為空,年齡大于20歲的用戶 wrapper.isNotNull("name") .isNotNull("email") .ge("age",20); List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
2.查詢名字等于“Tom”的用戶
@Test void test2(){ //查詢名字等于“Tom”的用戶 /*HashMap<String, Object> map = new HashMap<>(); map.put("name","Tom"); List<User> users = userMapper.selectByMap(map);*/ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","Tom"); //List<User> users = userMapper.selectList(wrapper); //users.forEach(System.out::println); //查詢一個用selectOne User user = userMapper.selectOne(wrapper); System.out.println(user); }
3.查詢年齡在20~30歲之間的用戶
@Test void test3(){ //查詢年齡在20~30歲之間的用戶 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.between("age",20,30); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
4.查詢名字里面包含"三",且"三"在右邊的用戶
@Test void test4(){ //查詢名字里面包含"三",且"三"在右邊的用戶 QueryWrapper<User> wrapper = new QueryWrapper<>(); //左:%val,右:val% wrapper.likeLeft("name","三"); //List<User> users = userMapper.selectList(wrapper); //也可以用selectMaps List<Map<String, Object>> maps = userMapper.selectMaps(wrapper); maps.forEach(System.out::println); }
5.根據(jù)id查詢用戶,但id不是直接賦值,而是根據(jù)查詢語句(子查詢)得到
@Test void test5(){ //根據(jù)id查詢用戶,但id不是直接賦值,而是根據(jù)查詢語句(子查詢)得到 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("id","select id from user where id<4"); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
6.根據(jù)id降序排序
@Test void test6(){ //根據(jù)id降序排序 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("id"); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
六、代碼自動生成器
package edu.ayit.utils; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.ArrayList; //代碼自動生成器 public class MyGenerator { public static void main(String[] args) { //需要構(gòu)建一個代碼自動生成器對象 AutoGenerator generator = new AutoGenerator(); //配置生成策略 //1.全局配置,generator包下的GlobalConfig GlobalConfig globalConfig = new GlobalConfig();//generator包下的GlobalConfig //當(dāng)前項(xiàng)目路徑 String projectPath = System.getProperty("user.dir"); //指定自動生成文件存儲的位置 globalConfig.setOutputDir(projectPath+"/src/main/java"); globalConfig.setAuthor("周");//作者 globalConfig.setOpen(false);//是否打開資源管理器 globalConfig.setFileOverride(false);//是否覆蓋 globalConfig.setServiceName("%sService");//去Service層接口的"I"前綴 globalConfig.setIdType(IdType.ID_WORKER);//設(shè)置主鍵自動生成策略 globalConfig.setDateType(DateType.ONLY_DATE);//配置日期類型 globalConfig.setSwagger2(true);//開啟Swagger generator.setGlobalConfig(globalConfig); //2.設(shè)置數(shù)據(jù)源 DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setUsername("root"); dataSourceConfig.setPassword("123456"); dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver"); dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"); dataSourceConfig.setDbType(DbType.MYSQL); generator.setDataSource(dataSourceConfig); //3.包的配置 PackageConfig packageConfig = new PackageConfig(); packageConfig.setModuleName("my");//默認(rèn)是null packageConfig.setParent("edu.ayit");//默認(rèn)是com.baomidou /*默認(rèn)值 packageConfig.setEntity("entity"); packageConfig.setMapper("mapper"); packageConfig.setService("service"); packageConfig.setController("controller"); */ generator.setPackageInfo(packageConfig); //4.策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user");/**設(shè)置要映射的表名,可以寫多個(重要)*/ //下劃線轉(zhuǎn)駝峰命名 strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); //自動lombok strategy.setEntityLombokModel(true); //邏輯刪除 strategy.setLogicDeleteFieldName("deleted"); //自動填充 TableFill createTime = new TableFill("create_time", FieldFill.INSERT); TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE); ArrayList<TableFill> tableFills = new ArrayList<>(); tableFills.add(createTime); tableFills.add(updateTime); strategy.setTableFillList(tableFills); //樂觀鎖 strategy.setVersionFieldName("version"); generator.setStrategy(strategy); //執(zhí)行 generator.execute(); } }
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring boot security設(shè)置忽略地址不生效的解決
這篇文章主要介紹了spring boot security設(shè)置忽略地址不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07線程池之newCachedThreadPool可緩存線程池的實(shí)例
這篇文章主要介紹了線程池之newCachedThreadPool可緩存線程池的實(shí)例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Intellij IDEA如何去掉@Autowired 注入警告的方法
這篇文章主要介紹了Intellij IDEA如何去掉@Autowired 注入警告的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Mybatis-Plus使用ID_WORKER生成主鍵id重復(fù)的解決方法
本文主要介紹了Mybatis-Plus使用ID_WORKER生成主鍵id重復(fù)的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07SpringBoot引入Thymeleaf的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot引入Thymeleaf的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04springboot中將日志信息存儲在catalina.base中過程解析
這篇文章主要介紹了springboot中將日志信息存儲在catalina.base中過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09mybatis動態(tài)插入list傳入List參數(shù)的實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了mybatis動態(tài)插入list,Mybatis 傳入List參數(shù)的方法,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2018-04-04Java實(shí)現(xiàn)上傳網(wǎng)絡(luò)圖片到七牛云存儲詳解
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)上傳網(wǎng)絡(luò)圖片到七牛云存儲,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12