【Java萌新】MyBatis-Plus案例
MyBatis-Plus是什么?
https://baomidou.com/#/
Mybatis-Plus(簡稱MP)是一個 Mybatis 的增強(qiáng)工具,在 Mybatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡化開發(fā)、提高效率而生。這是官方給的定義,關(guān)于mybatis-plus的更多介紹及特性,可以參考mybatis-plus官網(wǎng)。那么它是怎么增強(qiáng)的呢?其實就是它已經(jīng)封裝好了一些crud方法,我們不需要再寫xml了,直接調(diào)用這些方法就行,就類似于JPA。
特性
- 無侵入 :只做增強(qiáng)不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般順滑
- 損耗小 :啟動即會自動注入基本 CURD,性能基本無損耗,直接面向?qū)ο蟛僮? BaseMapper
- 強(qiáng)大的 CRUD 操作 :內(nèi)置通用 Mapper、通用 Service,僅僅通過少量配置即可實現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求, 以后的簡單的增刪改查, 它不用自己寫了!
- 支持 Lambda 形式調(diào)用 :通過 Lambda 表達(dá)式,方便的編寫各類查詢條件,無需再擔(dān)心字段寫錯
- 支持主鍵自動生成 :支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
- 支持 ActiveRecord 模式 :支持 ActiveRecord 形式調(diào)用,實體類只需繼承 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ù)防誤操作
快速入門
地址: https://baomidou.com/guide/quick-start.html
使用第三方組件
- 導(dǎo)入對應(yīng)依賴
- 研究如何讓編寫配置
- 代碼如何編寫
- 提高拓展
步驟
創(chuàng)建數(shù)據(jù)庫
mybatis_plus
創(chuàng)建 user表
DROP TABLE IF EXISTS user;CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT '主鍵ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年齡',email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (id) );真實開發(fā)過程中, version(樂觀鎖)、delete(邏輯刪除)、gmt_create、gm_modified其對應(yīng)的數(shù)據(jù)庫 Data 腳本如下:
DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');創(chuàng)建SpringBoot項目
mybatis_plus
導(dǎo)入依賴
<!--數(shù)據(jù)庫驅(qū)動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mybatis-plus-boot-starter是自己開發(fā)的, 并非官方--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency>說明: 我們使用mybatis-plus可以節(jié)省我們大量代碼, 盡量不要導(dǎo)入mybtis和mybatis-plus! 版本差異
連接數(shù)據(jù)庫
spring.datasource.username=root spring.datasource.data-password=123456 spring.datasource.url=jdbc:mysql://cdb-q9atzwrq.bj.tencentcdb.com:10167/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # serverTimezone=GMT 時區(qū) 8.0以上版本需要添加否則會報錯傳統(tǒng)項目結(jié)構(gòu)對比使用mybatis-plus之后
- pojo-dao(連接mybatis, 配置mapper.xml文件)service-controller
- 使用mybatis-plus之后
- pojo
- mapper接口
- 使用
思考問題
- SQL誰幫我們寫好了? MyBatis-Plus都寫好了
方法哪里來? MyBatis-Plus都寫好了
配置日志
我們所有的SQL是不可見的, 我們希望知道它是怎么執(zhí)行的, 所以我們必須要看日志
(真正上線, 在下)
CRUD拓展
Insert
@Testvoid testInsert() {User user = new User();user.setName("掌上編程");user.setAge(19);user.setEmail("2460798168@qq.com");userMapper.insert(user);}數(shù)據(jù)庫插入的id的默認(rèn)值為:全局的唯一id
主鍵的策略
分布式系統(tǒng)唯一id生成:
默認(rèn)@TableId(type = IdType.ID_WORKER)private Long id;雪花算法:snowflake是Twitter開源的分布式ID生成算法,結(jié)果是一個long型的ID。其核心思想是:使用41bit作為毫秒數(shù),10bit作為機(jī)器的ID(5個bit是數(shù)據(jù)中心,5個bit的機(jī)器ID),12bit作為毫秒內(nèi)的流水號(意味著每個節(jié)點(diǎn)在每毫秒可以產(chǎn)生 4096 個 ID),最后還有一個符號位,永遠(yuǎn)是0。具體實現(xiàn)的代碼可以參看https://github.com/twitter/snowflake。
主鍵自增
我們需要配置主鍵自增
-
實體類字段上 @TableId(type = IdType.AUTO)
-
數(shù)據(jù)庫字段一定要自增!
-
再次測試插入即可
其他源碼檢測
public enum IdType {AUTO(0), //數(shù)據(jù)庫id自增NONE(1), //未設(shè)置主鍵INPUT(2), //手動輸入ID_WORKER(3),//默認(rèn)的全局idUUID(4), //全局唯一id uuidID_WORKER_STR(5); //ID_WORKER 字符串表示法private int key;private IdType(int key) {this.key = key;}public int getKey() {return this.key;} }更新操作
@Testvoid testUpdate() {User user = new User();//通過條件自動拼接動態(tài)sqluser.setId(1L);user.setEmail("21211@qq.com");int i = userMapper.updateById(user);System.out.println(i);}自動填充
創(chuàng)建時間、更改時間! 這些操作一遍都是自動化完成的, 我們不希望手動更新!
阿里巴巴開發(fā)手冊:所有的數(shù)據(jù)表:gm_create、 gmt_modified 幾乎所有的表都需要配置上!而且需要自動化!
方式一 數(shù)據(jù)庫級別
- 在表中新增字段create_time、 update_time
方式二:代碼級別
數(shù)據(jù)庫的時間默認(rèn)值去掉
直接在實體類中
package cn.com.codingce.pojo;import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.Date;/*** @author xzMa*/ @Data @AllArgsConstructor @NoArgsConstructor public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;}MyMetaObjectHandler
package cn.com.codingce.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component;import java.util.Date;/*** 自己寫的處理器* @author xzMa*/ @Slf4j @Component //一定不要把我們的處理器加到IOC中 public class MyMetaObjectHandler implements MetaObjectHandler {//插入時的填充策略@Overridepublic void insertFill(MetaObject metaObject) {log.info("Start insert fill ...");//String fieldName, Object fieldVal, MetaObject metaObjectthis.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}//更新時的填充策略@Overridepublic void updateFill(MetaObject metaObject) {log.info("Start update fill ...");this.setFieldValByName("updateTime", new Date(), metaObject);} }樂觀鎖
在面試過程中, 我們經(jīng)常會被問到的樂觀鎖, 悲觀鎖! 這個其實非常簡單!
樂觀鎖:樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。
故名思意十分樂觀, 它總是認(rèn)為不會出現(xiàn)問題, 無論干什么都不去上鎖! 如果出現(xiàn)問題, 再次更新新值測試(version new version)
悲觀鎖:故名思意十分悲觀, 它總認(rèn)為總是出現(xiàn)問題, 無論干什么都會上鎖! 再去操作!
樂觀鎖機(jī)制:
- 取出記錄記錄, 獲取當(dāng)前version
- 更新時, 帶上這個version
- 執(zhí)行更新時, set version = new Version where version = oldVersion
- 如果version不對, 就更新失敗
測試MP樂觀鎖插件
- 給數(shù)據(jù)庫中添加version字段
- 我們對實體類添加對應(yīng)的字段
- 注冊組件
- 測試
查詢操作
@Testpublic void select() {User user = userMapper.selectById(1L);System.out.println(user);}@Testpublic void selectBatchIds() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));users.forEach(System.out::println);}//條件查詢 map@Testpublic void testSelectByBathIds() {HashMap<String, Object> map = new HashMap<>();//自定義要查詢map.put("name", "xzMhehe222");map.put("age", 12);List<User> userList = userMapper.selectByMap(map);userList.forEach(System.out::println);}分頁查詢
分頁在網(wǎng)站使用的十分之多
- 原始的limit進(jìn)行分頁
- pageHelper第三方插件
- MP其實也內(nèi)置了分頁插件
如何使用
配置攔截器組件
//Spring boot方式 @Configuration @MapperScan("com.baomidou.cloud.service.*.mapper*") public class MybatisPlusConfig {@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();} }- 直接使用Page插件即可
基本刪除操作
//真刪@Testpublic void testDelete() {userMapper.deleteById(1L);}//批量刪除@Testpublic void testDeleteBatchId() {userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));}//通過map刪除@Testpublic void testDeleteMap() {HashMap<String, Object> map = new HashMap<>();map.put("name", "xzMhehe");userMapper.deleteByMap(map);}我們在工作中會遇到一些問題:邏輯刪除
邏輯刪除
物理刪除:從數(shù)據(jù)庫中直接刪除
邏輯刪除:在數(shù)據(jù)庫中沒有移除,而是通過一個變量讓他失效! deleted = 0 =>deleted = 1
管理員可以查看刪除記錄!防止數(shù)據(jù)丟失,類似于回收站
- 在數(shù)據(jù)庫中添加deleted字段
- 在實體類中添加屬性
- 配置
性能分析插件
在平時開發(fā)中, 會遇到一些慢sql. 測試!druid
MP也提供性能分析插件, 如果超過這個時間停止運(yùn)行!
- 導(dǎo)入插件
- 測試使用
條件構(gòu)造器
十分重要 Wrapper
- 測試1
- 測試2
代碼自動生成器
dao pojo service controller 都是自動生成
package cn.com.codingce.generator;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 CodeGenerator {public static void main(String[] args) {// 1、創(chuàng)建代碼生成器AutoGenerator mpg = new AutoGenerator();// 2、全局配置GlobalConfig gc = new GlobalConfig();//當(dāng)前的項目路徑String projectPath = System.getProperty("user.dir");//所有代碼都會生成到 /src/main/java 路徑下gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("小馬Coding");gc.setOpen(false); //生成后是否打開資源管理器gc.setFileOverride(false); //重新生成時文件是否覆蓋gc.setServiceName("%sService"); //去掉Service接口的首字母Igc.setIdType(IdType.ID_WORKER_STR); //主鍵策略gc.setDateType(DateType.ONLY_DATE);//定義生成的實體類中日期類型gc.setSwagger2(true);//開啟Swagger2模式mpg.setGlobalConfig(gc);// 3、數(shù)據(jù)源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://cdb-q9atzwrq.bj.tencentcdb.com:10167/codingstudy?useUnicode=true&characterEncoding=utf-8&useSSL=false");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);// 4、包配置PackageConfig pc = new PackageConfig();pc.setModuleName("blog");pc.setParent("cn.com.codingce");pc.setController("controller");pc.setEntity("pojo");pc.setService("service");pc.setMapper("mapper");mpg.setPackageInfo(pc);// 5、策略配置StrategyConfig strategy = new StrategyConfig();//strategy.setInclude("ze_user");//設(shè)置要映射的表名//strategy.setInclude("ze_user", "ze_course");//可設(shè)置多個strategy.setInclude("ze_user");//設(shè)置要映射的表名strategy.setNaming(NamingStrategy.underline_to_camel);//數(shù)據(jù)庫表映射到實體的命名策略strategy.setTablePrefix("ze_");//設(shè)置表前綴不生成strategy.setColumnNaming(NamingStrategy.underline_to_camel);//數(shù)據(jù)庫表字段映射到實體的命名策略strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter鏈?zhǔn)讲僮?/span>strategy.setRestControllerStyle(true); //restful api風(fēng)格控制器strategy.setControllerMappingHyphenStyle(true); //url中駝峰轉(zhuǎn)連字符//strategy.setLogicDeleteFieldName("deleted"); //邏輯刪除字段//自動填充配置//TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);//TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);//ArrayList<TableFill> tableFills = new ArrayList<>();//tableFills.add(gmtCreate);//tableFills.add(gmtModified);//strategy.setTableFillList(tableFills);mpg.setStrategy(strategy);// 6、執(zhí)行mpg.execute();} }項目地址
https://github.com/xzMhehe/codingce-java/tree/master/mybatis_plus
總結(jié)
以上是生活随笔為你收集整理的【Java萌新】MyBatis-Plus案例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10redis闪退
- 下一篇: Java助力期末