MyBatisPlus詳解 官網鏈接: "鏈接" 簡介 MyBatis Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。 MyBatis 最好的搭檔,就像 魂鬥羅 中的 1P、2P,基友搭配,效率翻倍。 為什麼要學習它 ...
MyBatisPlus詳解
官網鏈接:鏈接
簡介
MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis
的基礎上只做增強不做改變,為簡化開發、提高效率而生。
MyBatis 最好的搭檔,就像 魂鬥羅 中的 1P、2P,基友搭配,效率翻倍。
為什麼要學習它呢?
MyBatisPlus可以節省我們大量工作時間,所有的CRUD代碼它都可以自動化完成!
特性
支持資料庫
架構
快速開始
- 創建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)
);
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
- 創建springboot項目,導入依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
3. 配置 連接資料庫
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
- 編寫實體類
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- 編寫Mapper類
public interface UserMapper extends BaseMapper<User> {
}
- 創建啟動類
@SpringBootApplication
@MapperScan("com.mybatisplus.mybatisplus.mapper")
public class MybatisplusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusApplication.class, args);
}
}
- 測試
查詢全部用戶
@SpringBootTest
class MybatisplusApplicationTests {
@Autowired
UserMapper mapper;
@Test
void contextLoads() {
List<User> users = mapper.selectList(null);
users.forEach(System.out::println);//列印輸出
}
}
通過以上幾個簡單的步驟,我們就實現了 User 表的 CRUD 功能,甚至連 XML 文件都不用編寫!
從以上步驟中,我們可以看到集成MyBatis-Plus非常的簡單,只需要引入 starter 工程,並配置 mapper 掃描路徑即可。
但 MyBatis-Plus 的強大遠不止這些功能,想要詳細瞭解 MyBatis-Plus 的強大功能?那就繼續往下看吧!(官網原話)
配置日誌
所以的sql不可見,我們需要觀看sql是怎麼執行的
#mybatis日誌配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
CRUD拓展
insert插入
@Test
public void testinsert(){
User u=new User();
u.setName("joker_dj");
u.setAge(18);
u.setEmail("[email protected]");
mapper.insert(u);
}
ID會自動生成
常見的id生成有
id生成策略
博客:鏈接
雪花演算法
自增ID:對於數據敏感場景不宜使用,且不適合於分散式場景。
GUID:採用無意義字元串,數據量增大時造成訪問過慢,且不宜排序。
最高位是符號位,始終為0,不可用。
41位的時間序列,精確到毫秒級,41位的長度可以使用69年。時間位還有一個很重要的作用是可以根據時間進行排序。
10位的機器標識,10位的長度最多支持部署1024個節點。
12位的計數序列號,序列號即一系列的自增id,可以支持同一節點同一毫秒生成多個ID序號,12位的計數序列號支持每個節點每毫秒產生4096個ID序號。
原文:鏈接
測試不同的主鍵自增策略
自增策略
public enum IdType {
AUTO(0),//主鍵自增
NONE(1),//不使用
INPUT(2),//手動輸入
ID_WORKER(3),//預設全局唯一Id
UUID(4),//全局唯一id uuid
ID_WORKER_STR(5);//字元串表示法
}
update更新
自動填充
創建時間、修改時間、這些操作是自動化完成的,我們不希望手動更新
阿裡巴巴手冊:所有數據表:gmt_create、gmt_modified幾乎所有的表都要配置上!而且需要自動化!
方式一:資料庫級別
- 在表中新增欄位 create_time, update_time
再次測試,同步實體類
運行測試
方式二:代碼級別
- 刪除資料庫的預設值
- 實體類上增加註解
- 編寫handler策略
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/*插入時的填充策略*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("填充....");//setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
/*更新時的填充策略*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("更新....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
樂觀鎖
在面試過程中,我們經常會被問道樂觀鎖,悲觀鎖!這個其實非常簡單!
樂觀鎖 : 故名思意十分樂觀,它總是認為不會出現問題,無論乾什麼不去上鎖!如果出現了問題, 再次更新值測試
悲觀鎖:故名思意十分悲觀,它總是認為總是出現問題,無論乾什麼都會上鎖!再去操作!
樂觀鎖實現方式:
取出記錄時,獲取當前version
更新時,帶上這個version
執行更新時, set version = newVersion where version = oldVersion
如果version不對,就更新失敗
測試mybatisplus的樂觀鎖
添加欄位 預設值為1
同步實體類
配置樂觀鎖
@EnableTransactionManagement
@Configuration
public class Config {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
測試樂觀鎖成功案例
會發現更新操作時預設帶上version
失敗案例
第二次修改並沒有成功
select查詢操作
@Test
public void testselect01(){//查詢單個用戶
User user = mapper.selectById(1L);
System.out.println(user);
}
@Test
public void testselect02(){//查詢多個用戶 批量查詢
List<User> users = mapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
//條件查詢 map方式
@Test
public void testselect03(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","joker_dj2");//查詢欄位name為joker_dj2的結果
map.put("age",18);//查詢欄位age為18的值
//...
List<User> users = mapper.selectByMap(map);
System.out.println(users);
}
分頁查詢
分頁插件有很多
- 原始的limit進行1分頁
- pageHelper第三方插件
- MybatisPlus內置插件
如何使用
配置config
//分頁插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
直接使用即可
//分頁插件
@Test
public void testPage(){
//參數一:當前頁
//參數二:頁面大小
Page<User> objectPage = new Page<>(1, 5);//第1頁,5行數據
mapper.selectPage(objectPage, null);//分頁查詢 條件為null
objectPage.getTotal();//獲取總記錄數
objectPage.getRecords();//獲取數據
objectPage.getRecords().forEach(System.out::println);//列印輸出
}
刪除操作
//刪除操作 根據ID刪除 單個
@Test
public void Testdelete(){
mapper.deleteById(5L);
}
@Test//批量刪除
public void testdelete02(){
mapper.deleteBatchIds(Arrays.asList(1,2,3));//刪除id為1 2 3 的用戶
}
//通過map操作
@Test
public void testmapdelete(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","joker_dj2");//刪除name為joker_dj2的用戶
mapper.deleteByMap(map);
}
邏輯刪除
- 物理刪除:從資料庫直接移除
- 邏輯移除:在資料庫中沒有直接刪除,而是通過一個變數讓他失效
場景:
管理員可以查看被刪除的數據,防止數據丟失,類似於回收站
使用:
3. 在資料庫中增加一個delete欄位 預設值為0
- 實體類同步
- 配置邏輯刪除
測試刪除
可以看到,測試的是刪除操作,實際上走的是更新操作,並不是刪除操作
測試查詢 會跟上where deleted=0的sql 非管理員
性能分析插件
我們在平時的開發中,會遇到一些慢sql。測試! druid,,,,,
作用:性能分析攔截器,用於輸出每條 SQL 語句及其執行時間
mybatisplus也提供性能分析插件,如果超過這個時間就停止運行!
使用
-
導入插件
-
配置項目為測試環境
條件構造器
Wrapper十分重要
複雜的sql就靠它
使用
- 判斷空
//查詢name不為空,並且郵箱不為空的用戶,年齡大於18的用戶
@Test
public void testwrapper(){
QueryWrapper<User> Wrapper = new QueryWrapper<>();
Wrapper
.isNotNull("name")//查詢不為空的用戶
.isNotNull("email")//箱不為空
.ge("age",19);//年齡大於18的用戶 19>18
;
mapper.selectList(Wrapper);
}
2. 等於,模糊查詢
@Test
public void test01(){//查詢一個name等於joker_dj的用戶
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","joker_dj");
mapper.selectOne(wrapper);
}
@Test
public void test02(){//查詢年齡在18-21的用戶個數
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",18,21);
Integer integer = mapper.selectCount(wrapper);
System.out.println(integer);
}
@Test
public void test03(){//模糊查詢
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.notLike("name","j")//查詢姓名不包含j的用戶
.likeRight("email","t") //左和右likeLeft '%t' likeRight 't%'
;
List<Map<String, Object>> maps = mapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
- 子查詢
- 排序
代碼生成器
dao、pojo、service、controller都給我自己去編寫完成!
AutoGenerator 是 MyBatis-Plus 的代碼生成器,通過 AutoGenerator 可以快速生成 Entity、
Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,極大的提升了開發效率。
- 導入依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis和mybatisplus最好只導入其中一個-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
</dependencies>
- 編寫生成器代碼
public static void main(String[] args) {
// 需要構建一個 代碼自動生成器 對象
AutoGenerator mpg = new AutoGenerator();
// 配置策略
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");//獲取目錄
gc.setOutputDir(projectPath + "/src/main/java");//輸出目錄
gc.setAuthor("joker_dj");//設置作者
gc.setOpen(false);//是否打開資源管理器
gc.setFileOverride(false); // 是否覆蓋
gc.setServiceName("%sService"); // 去Service的I首碼
gc.setIdType(IdType.AUTO);//設置主鍵的演算法 //對應數據的主鍵(uuid,自增ID,雪花演算法,redis,zookeeper)
gc.setDateType(DateType.ONLY_DATE);//日期類型
gc.setSwagger2(true);//是否配置Swagger2
mpg.setGlobalConfig(gc);
//2、設置數據源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);//配置資料庫類型 mysql
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("codegeneration");//模塊名稱
pc.setParent("com.dj");//配置工程包名稱
pc.setEntity("entity");//配置entity的包名
pc.setMapper("mapper");//配置mapper的包名
pc.setService("service");//配置service的包名
pc.setController("controller");//配置controller的包名
mpg.setPackageInfo(pc);//配置包
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("user"); ////設置映射的表名 多個表strategyConfig.setInclude("user","cloud","...");
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//欄位名轉駝峰命名
strategy.setEntityLombokModel(true); // 自動lombok;
strategy.setLogicDeleteFieldName("deleted");//邏輯刪除的欄位名稱
// 自動填充配置
TableFill create_time = new TableFill("create_time", FieldFill.INSERT);//自動填充更新的欄位
TableFill update_time = new TableFill("update_time", FieldFill.INSERT_UPDATE);//自動更新的欄位
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(create_time);//創建的策略
tableFills.add(update_time);//更新的策略
strategy.setTableFillList(tableFills);
// 樂觀鎖
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
mpg.execute(); //執行
}