1. MyBatis 存在的痛點
我們知道 MyBatis 是一個基于 JAVA 的持久層框架,它內部封裝了 jdbc,極大提高了我們的開發效率。
但是使用 Mybatis 開發也有很多痛點:
- 每個 Dao 接口都需要自己定義一堆增刪改查方法。
/**
* @Desc: UserDao 接口
* @Author: 公眾號:知否技術
* @date: 下午7:43 2022/5/7
*/
public interface UserDao {
// 獲取所有用戶信息
List<User> getUserList();
// 根絕 id 獲取用戶信息
User getUserById(int id);
// 新增用戶信息
boolean add(User user);
// 更新用戶信息
boolean update(User user);
// 刪除用戶信息
boolean delete(int id);
}
復制代碼
2.每個 MApper 文件都需要寫一堆基本的增刪改查語句。
3.如果查詢的列表需要分頁,我們還需要給查詢方法封裝成分頁對象。
你可能會說:Mybatis 還能有痛點?用著多方便!
對于小項目而言,用著確實還行。但是遇到大項目,光 Dao 接口都有幾百個,如果還要手動定義一堆增刪改查方法和 sql 語句,那也很浪費時間。
那有沒有這樣一個框架:
1.封裝了 Mybatis,自帶 CRUD 方法,我們不需要自己定義 CRUD 方法。
2.提供各種查詢方法,不需要在 mapper 文件中寫一些基礎的 sql 語句。
3.封裝了分頁功能,讓分頁查詢無比絲滑。
有的,MybatisPlus 閃亮登場。
2. 邂逅 MybatisPlus
官網:
https://baomidou.com/
復制代碼
MybatisPlus 是在 Mybatis 原有功能的基礎上進行了封裝。它不做改變,而是增強了 Mybatis 的功能。
我們不用寫 mappe.xml ,直接調用它的 API 就能完成 CRUD 和各種查詢操作。
而且它自帶分頁插件等一些高級功能,極大地提高了我們的開發效率。
3. 入門案例
開發環境:
- 開發工具:IDEA
- 構建工具:Maven
- 數據庫:MySQL
- 項目框架:SpringBoot
1.新建 SpringBoot 項目
2.引入依賴
<!-- mybatis-plus 依賴-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!-- mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
復制代碼
3.創建數據庫表
user 表:
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1508421137384648706 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
復制代碼
4.實體類
public class User {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
復制代碼
5.修改 application.yml
server:
port: 8082
servlet:
context-path: /mybatisplus_demo
# 數據源配置
spring:
datasource:
username: root
password: 12345678
url: jdbc:mysql://localhost:3306/ssm?allowPublicKeyRetrieval=true&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
復制代碼
6.新建 UserMapper 接口
注:
(1)因為 mybatis 規定:mapper.xml 文件的名字要和接口名字一樣,所以很多人習慣將 Dao 接口命名為 xxxMapper。
(2)BaseMapper 是 MybatisPlus 內置的接口,它包含基本的 CRUD 方法。
7.啟動類添加 @MapperScan 注解
8.測試
@SpringBootTest
public class MybatisPlusDemoApplicationTests {
@Resource
private UserMapper userMapper;
@Test
void testMybatisPlus() {
for (int i = 18; i < 20; i++) {
User user = new User("王小波" + i, i);
userMapper.insert(user);
}
}
}
9.總結
我們發現只要繼承 MybatisPlus 的BaseMapper,就能完成基本的增刪改查操作,非常方便。
4. 基本增刪改查
1.新增
User user = new User("王小波", 19);
userMapper.insert(user);
復制代碼
2.編輯
根據 id 更新數據
int rows = userMapper.updateById(user);
if(rows>0){
System.out.println("更新成功");
}
復制代碼
3.刪除
根據主鍵刪除信息
userMapper.deleteById("152635612");
復制代碼
根據 map 條件刪除信息
Map<String, Object> param = new HashMap<>();
param.put("age", 18);
int rows = userMapper.deleteByMap(param);
if (rows > 0) {
System.out.println("刪除成功!");
}
復制代碼
根據 id 集合批量刪除
List<Integer> ids = Stream.of(110, 112, 113, 115).collect(Collectors.toList());
int rows = userMapper.deleteBatchIds(ids);
if (rows > 0) {
System.out.println("刪除成功!");
}
復制代碼
4.查詢
根據 id 查詢
User user = userMapper.selectById(152382374);
復制代碼
根據 map 條件查詢
Map<String, Object> param = new HashMap<>();
param.put("age", 18);
List<User> userList = userMapper.selectByMap(param);
復制代碼
根據 id 集合批量查詢
List<Integer> ids = Stream.of(110, 112, 113, 115).collect(Collectors.toList());
List<User> userList = userMapper.selectBatchIds(ids);
復制代碼
5. 構造器
MybatisPlus 提供了查詢構造器和更新構造器用來生成帶有 where 條件的 sql 語句。
(1)封裝查詢條件的構造器:
QueryWrapper
復制代碼
常用查詢條件:
等于:eq
QueryWrapper<User> userWrapper = new QueryWrapper<>();
// 查詢名字是張三的用戶
userWrapper.eq("name","張三");
List<User> userList = userMapper.selectList(userWrapper);
復制代碼
不等于:ne
QueryWrapper<User> userWrapper = new QueryWrapper<>();
userWrapper.ne("name","張三");
// 查詢名字不是張三的用戶
List<User> userList = userMapper.selectList(userWrapper);
復制代碼
模糊查詢:like
QueryWrapper<User> userWrapper = new QueryWrapper<>();
// 模糊查詢
userWrapper.like("name","張");
List<User> userList = userMapper.selectList(userWrapper);
復制代碼
降序:orderByDesc
QueryWrapper<User> userWrapper = new QueryWrapper<>();
// 模糊查詢并根據 number 倒序
userWrapper.like("name","張").orderByDesc("number");
List<User> userList = userMapper.selectList(userWrapper);
復制代碼
升序:orderByAsc
QueryWrapper<User> userWrapper = new QueryWrapper<>();
// 模糊查詢并根據 number 降序
userWrapper.like("name","張").orderByAsc("number");
List<User> userList = userMapper.selectList(userWrapper);
復制代碼
其他常用的條件可以去官網查看相關文檔,這里不再過多贅述:
https://baomidou.com/pages/10c804/#in
復制代碼
(2)封裝更新條件的構造器:
UpdateWrapper
復制代碼
UpdateWrapper 的 where 條件和 QueryWrapper 的一樣,只不過需要 set 值。
UpdateWrapper<User> userWrapper = new UpdateWrapper<>();
userWrapper.set("name","王小波").set("age",22)
.eq("name","張三");
復制代碼
6. 通用 Service
MybatisPlus 中有一個通用的接口 Iservice 和實現類,封裝了常用的增刪改查等操作。
1.新建 service 和 實現類
UserService
/**
* @Desc:
* @Author: 公眾號:知否技術
* @date: 下午9:57 2022/5/11
*/
public interface UserService extends IService<User> {
}
復制代碼
UserServiceImpl
/**
* @Desc:
* @Author: 公眾號:知否技術
* @date: 下午9:57 2022/5/11
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
復制代碼
2.測試
我們發現該 IService 接口封裝了一些常用的方法,極大地提高了我們的開發效率。
7. 常用注解
1.@TableId
MybatisPlus 會默認將實體類中的 id 作為主鍵。
@TableId 表示 id 的生成策略,常用的有兩種:
(1) 基于數據庫的自增策略
(2) 使用雪花算法策略隨機生成
2.@TableName
如果實體類和數據庫的表名不一致,可以使用這個注解做映射
例如:
3.@TableField
當表屬性和實體類中屬性名不一致時,可以使用這個注解做映射:
8. 分頁
MybatisPlus 內部封裝了分頁插件,只用簡單配置一下就能實現分頁功能。
1.配置類
/**
* @Desc:
* @Author: 公眾號:知否技術
* @date: 下午9:31 2022/5/11
*/
@Configuration
@MapperScan("com.zhifou.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
復制代碼
2.測試
@Test
void testMybatisPlus() {
int current = 1;
int size = 10;
Page<User> userPage = new Page<>(current, size);
//獲取分頁數據
List<User> list = userPage.getRecords();
list.forEach(user->{
System.out.println(user);
});
Page<User> page = userMapper.selectPage(userPage, null);
System.out.println("當前頁:" + page.getCurrent());
System.out.println("每頁條數:" + page.getSize());
System.out.println("總記錄數:" + page.getTotal());
System.out.println("總頁數:" + page.getPages());
}
復制代碼
9. 代碼生成器
MybatisPlus 可以幫助我們自動生成 controller、service、dao、model、mapper.xml 等文件,極大地提高了我們的開發效率。
1.引入依賴
<!-- 代碼生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
復制代碼
2.代碼生成器工具類
public class CodeGenerator {
public static void main(String[] args) {
// 連接數據庫
FastAutoGenerator.create("jdbc:mysql://localhost:3306/ssm?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC", "root", "123456")
.globalConfig(builder -> {
builder.author("知否技術") // 設置作者
.fileOverride() // 覆蓋已生成文件
// 設置日期時間
.dateType(DateType.ONLY_DATE)
.outputDir("D:\WorkSpace\idea\mybatisplus_demo\src\main\java"); // 指定輸出目錄
})
.packageConfig(builder -> {
builder.parent("com.zhifou") // 設置父包名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D:\WorkSpace\idea\mybatisplus_demo\src\main\resources\mapper")); // 設置mapperXml生成路徑
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 設置需要生成的表名
.addTablePrefix("t_"); // 設置過濾表前
// 新增數據,自動為創建時間賦值
IFill createFill = new Column("created_date", FieldFill.INSERT);
IFill updateFill = new Column("updated_date", FieldFill.UPDATE);
builder.entityBuilder()
// 設置id類型
.idType(IdType.ASSIGN_ID)
// 開啟 Lombok
.enableLombok()
// 開啟連續設置模式
.enableChainModel()
// 駝峰命名模式
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
// 自動為創建時間、修改時間賦值
.addTableFills(createFill).addTableFills(updateFill)
// 邏輯刪除字段
.logicDeleteColumnName("is_deleted");
// Restful 風格
builder.controllerBuilder().enableRestStyle();
// 去除 Service 前綴的 I
builder.serviceBuilder().formatServiceFileName("%sService");
// mapper 設置
builder.mapperBuilder()
.enableBaseResultMap()
.enableBaseColumnList();
})
// 固定
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默認的是Velocity引擎模板
.execute();
}
}
復制代碼
關鍵點:
(1)配置數據庫連接信息。
自動生成代碼需要連接數據庫
(2)指定輸出目錄,這里直接設置你項目的目錄,到時候不用賦值粘貼了。
(3)設置父包名。
(4)設置表名
然后右鍵運行,代碼就會自動生成。
10. application.yml 配置
# MybatisPlus
mybatis-plus:
global-config:
db-config:
column-underline: true # 駝峰形式
logic-delete-field: isDeleted # 全局邏輯刪除的實體字段名
logic-delete-value: 1 # 邏輯已刪除值(默認為 1)
logic-not-delete-value: 0 # 邏輯未刪除值(默認為 0)
db-type: mysql
id-type: assign_id # id策略
table-prefix: t_ # 配置表的默認前綴
mapper-locations: classpath*:/mapper/**Mapper.xml # mapper 文件位置
type-aliases-package: com.zhifou.entity # 實體類別名
configuration:
log-impl: org.Apache.ibatis.logging.stdout.StdOutImpl # 日志:打印sql 語句
復制代碼
11. 完整代碼
鏈接: https://pan.baidu.com/s/1nlRjKOWs3ON53Dh1XXLKGw
提取碼: 9un7
復制代碼
12. 遇到的坑
1.傳參為 0 時,查詢語句失效。
例如傳遞的 age 為 0,查詢就會失效
<select id="getUser" resultType="user">
select id,name,age,sex from user
<where>
<if test="age != null and age !='' ">
age = #{age}
</if>
</where>
</select>
復制代碼
原因:判斷 int 是否為空只要 !=null 就行了,如果加上 type != '',0 會被轉為 null。
2.MybatisPlus 更新字段為 null 失敗
解決辦法:
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String name;
復制代碼
該注解會忽略為空的判斷,