MyBatisPlus 快速入門 1.創建資料庫mybatisplus 2.創建user表並插入數據 DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主鍵ID', name VARCHAR( ...
MyBatisPlus
快速入門
1.創建資料庫mybatisplus
2.創建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)
);
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]');
-- 真實開發中一般還需要version(樂觀鎖)、deleted(邏輯刪除)、gmt_create、gmt_modified
3.初始化SpringBoot項目
4.導入依賴
儘量不要同時導入mybatis和mybatisplus的依賴
<!-- 資料庫驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
5.連接資料庫
application.properties
# mysql 5 驅動不同 com.mysql.jdbc.Driver
# mysql 8 驅動不同com.mysql.cj.jdbc.Driver、需要增加時區的配置serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
6.傳統方式pojo-dao(連接mybatis,配置mapper.xml文件)-service-controller
6.使用MyBatisPlus
- pojo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- mapper介面
@Repository//持久層
public interface UserMapper extends BaseMapper<User> {
}
- 測試類
首先在主類中配置mapper掃描
@MapperScan("com.xust.mapper")
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//參數是一個Wrapper,條件構造器,這裡先不用
List<User> users=userMapper.selectList(null);
users.forEach(System.out::println);
}
}
配置日誌
在開發中使用,通過日誌查看sql如何執行
applicatiohn.properties
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
CRUD擴展
插入
@SpringBootTest
class MybatisPlusApplicationTests {
// 測試插入
@Test
public void testInsert() {
User user = new User();
user.setName("xust");
user.setAge(3);
user.setEmail("[email protected]");
int result = userMapper.insert(user); // 幫我們自動生成id
System.out.println(result); // 受影響的行數
System.out.println(user); // 發現,id會自動回填
}
}
更新
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
//測試更新
@Test
public void testUpdate(){
User user = new User();
user.setId(1L);
user.setName("xxx");
userMapper.updateById(user);
}
}
自動填充
創建時間、修改時間!這些個操作一遍都是自動化完成的,我們不希望手動更新
我這裡使用的是SQLyog
資料庫級別操作
代碼級別操作
1.首先恢復清除資料庫中預設值和更新效果
2.實體類欄位屬性上需要增加註解
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.INPUT) //一旦手動輸入id後就需要自己配置id了
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;
}
3.編寫處理器來處理這個註解
@Slf4j
@Component //將處理器加入到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入時的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill...........");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新時的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill...........");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
樂觀鎖
意圖:
當更新一條數據時,希望這條數據沒有被其他人更新。
- 樂觀鎖:它總是認為不會出現問題,無論乾什麼不去上鎖!如果出現了問題,再次更新值測試
- 悲觀鎖:它總是認為總是出現問題,無論乾什麼都會上鎖!再去操作
樂觀鎖實現方式:
- 取出記錄時,獲取當前version
- 更新時帶上version
- 執行更新時,set version=newVersion where version=oldVersion
- 如果version不對,就更新失敗
樂觀鎖:1、先查詢,獲得版本號 version = 1
-- A
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
-- B 線程搶先完成,這個時候 version = 2,會導致 A 修改失敗!
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
測試
1. 資料庫添加version欄位
2.實體類加對應欄位
@Version //樂觀鎖Version註解
private Integer version;
3.註冊組件
@EnableTransactionManagement
@Configuration // 配置類
public class MyBatisPlusConfig { // 註冊樂觀鎖插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4.測試
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
//測試樂觀鎖成功
@Test
public void testOptimisticLocker(){
//查詢用戶信息
User user = userMapper.selectById(1L);
//修改用戶信息
user.setName("yyy");
user.setEmail("[email protected]");
//執行更新操作
userMapper.updateById(user);
}
//測試樂觀鎖失敗
@Test
public void testOptimisticLocker2(){
//A
User user = userMapper.selectById(1L);
user.setName("yyy1");
user.setEmail("[email protected]");
//B,模擬另外一個線程執行了插隊操作
User user2 = userMapper.selectById(1L);
user2.setName("yyy2");
user2.setEmail("[email protected]");
//B執行更新
userMapper.updateById(user2);
//A執行更新,如果沒有樂觀鎖就會更新
userMapper.updateById(user);
}
}
查詢操作
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
// 測試查詢
@Test
public void testSelectById() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
// 測試批量查詢!
@Test
public void testSelectByBatchId() {
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
// 按條件查詢之使用map操作
@Test
public void testSelectByBatchIds() {
HashMap<String, Object> map = new HashMap<>();
// 自定義要查詢
map.put("name", "ccc");
map.put("age", 3);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
}
分頁查詢
1.配置攔截器組件
MyBatisPlusConfig.java
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
2.直接使用Page對象
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
//測試分頁查詢
@Test
public void testPage(){
//參數一:當前頁
//參數二:顯示條數
Page<User> page=new Page<>(1,3);
userMapper.selectPage(page,null);
//列印當前頁
page.getRecords().forEach(System.out::println);
//列印總數
System.out.println(page.getTotal());
}
}
刪除操作
根據id刪除
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
//測試刪除
@Test
public void testDeleteById() {
userMapper.deleteById(1579436224978829314L);
}
//批量刪除
@Test
public void testDeleteBatchId() {
userMapper.deleteBatchIds(Arrays.asList(1579459015811768322L, 1579459015811768324L));
}
//條件刪除map操作
@Test
public void testDeleteMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "ccc");
userMapper.deleteByMap(map);
}
}
邏輯刪除
物理刪除:從資料庫中直接移除
邏輯刪除:在資料庫中沒有直接移除,通過一個變數使其失效
1.在資料庫表中增加一個deleted欄位,為0表示沒刪
2.實體類中增加屬性
@TableLogic //邏輯刪除
private Integer deleted;
3.配置
MyBatisPlusConfig.java
// 邏輯刪除組件!
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
application.properties
# 配置邏輯刪除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
4.測試
執行之前的刪除操作,實際上進行的是update操作
性能分析插件
平時開發時會遇到一些慢SQL
作用:性能分析攔截器,用於輸出每條 SQL 語句及其執行時間
在測試和開發環境下使用
1.設置開發環境
application.properties
spring.profiles.active=dev
2.導入插件
MyBatisPlusConfig.java
@Bean
@Profile({"dev","test"}) //設置在dev、test環境開啟,保證效率
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor=new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100); //設置SQL執行的最大時間,超過則不執行
performanceInterceptor.setFormat(true); //是否開啟格式化,讓SQL查看起來更方便
return performanceInterceptor;
}
條件構造器(Wrapper)
比較重要,寫複雜的SQL可以用它來代替
@SpringBootTest
public class WrapperTest {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//查詢name不為空,email不為空,且年齡大於等於12的
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.isNotNull("name")
.isNotNull("email")
.ge("age",12);
userMapper.selectList(wrapper);
}
@Test
void test2() {
//查詢name為Tom的
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name","Tom");
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
@Test
void test3() {
//查詢年齡20~30的人
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.between("age",20,30);
Integer count= userMapper.selectCount(wrapper);//查詢結果數
System.out.println(count);
}
//模糊查詢
@Test
void test4() {
//name中不包含o,且email以t開頭
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.notLike("name","o")
.likeRight("email","t"); //相當於t%
List<Map<String, Object>> maps= userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
@Test
void test5() {
QueryWrapper<User> wrapper=new QueryWrapper<>();
//id在子查詢中查出來
wrapper.inSql("id","select id from user where id<3");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}
@Test
void test6() {
QueryWrapper<User> wrapper=new QueryWrapper<>();
//通過id進行排序
wrapper.orderByDesc("id");
List<User> list = userMapper.selectList(wrapper);
list.forEach(System.out::println);
}
}
代碼生成器
1.引入相關依賴,配置好資料庫
2.寫生成器
package com.xust;
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;
/**
* @Description: 代碼生成器
* @Author: XiePengXiong
* @Date: 2022/10/11 19:46
*/
public class generator {
public static void main(String[] args) {
//構建代碼生成器對象
AutoGenerator mpg = new AutoGenerator();
//配置策略
//1.全局配置************************************************************************************************************
GlobalConfig gc = new GlobalConfig(); //generator包下的
String projectPath = System.getProperty("user.dir"); //獲取當前項目路徑
gc.setOutputDir(projectPath + "/src/main/java"); //輸出目錄
gc.setAuthor("xpx"); //作者
gc.setOpen(false); //生成後是否打開資源管理器(文件夾)
gc.setFileOverride(false); //是否覆蓋上次生成的
gc.setServiceName("%sService"); //去Service的I首碼
gc.setIdType(IdType.ID_WORKER); //生成策略
gc.setDateType(DateType.ONLY_DATE); //日期類型
gc.setSwagger2(true); //Swagger
mpg.setGlobalConfig(gc); //將全局配置放入生成器中
//2.設置數據源************************************************************************************************************
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/kuang_community? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("xpx24167830");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//3、包的配置************************************************************************************************************
PackageConfig pc = new PackageConfig();
pc.setModuleName("blog");
pc.setParent("com.xust");
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置************************************************************************************************************
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("blog_tags", "course", "links", "sys_settings", "user_record", " user_say"); // 設置要映射的表名
strategy.setNaming(NamingStrategy.underline_to_camel); //下劃線轉駝峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel); //下劃線轉駝峰命名
strategy.setEntityLombokModel(true); // 自動lombok;
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);
// 樂觀鎖
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true); //開啟駝峰命名
strategy.setControllerMappingHyphenStyle(true); // url轉換成下劃線localhost:8080/hello_id_2
mpg.setStrategy(strategy);
//執行
mpg.execute();
}
}