一熟史、MyBatis-Plus簡介
1氧映、簡介
MyBatis-Plus(簡稱 MP)是一個(gè) MyBatis的增強(qiáng)工具钧萍,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變褐缠,為 簡化開發(fā)、提高效率而生风瘦。
我們的愿景是成為 MyBatis 最好的搭檔队魏,就像魂斗羅中的 1P、2P万搔,基友搭配胡桨,效率翻倍。
2瞬雹、特性
- 無侵入:只做增強(qiáng)不做改變昧谊,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑
- 損耗小:啟動(dòng)即會(huì)自動(dòng)注入基本 CURD酗捌,性能基本無損耗揽浙,直接面向?qū)ο蟛僮?/li>
- 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service意敛,僅僅通過少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作馅巷,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求
- 支持 Lambda 形式調(diào)用:通過 Lambda 表達(dá)式草姻,方便的編寫各類查詢條件钓猬,無需再擔(dān)心字段寫錯(cuò)
- 支持主鍵自動(dòng)生成:支持多達(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í)行時(shí)間,建議開發(fā)測試時(shí)啟用該功能捻爷,能快速揪出慢查詢
- 內(nèi)置全局?jǐn)r截插件:提供全表 delete 您市、 update 操作智能分析阻斷,也可自定義攔截規(guī)則役衡,預(yù)防誤操作
3、支持?jǐn)?shù)據(jù)庫
任何能使用
MyBatis
進(jìn)行 CRUD, 并且支持標(biāo)準(zhǔn) SQL 的數(shù)據(jù)庫薪棒,具體支持情況如下手蝎,如果不在下列表查看分頁部分教程 PR 您的支持。
- MySQL俐芯,Oracle棵介,DB2,H2吧史,HSQL邮辽,SQLite,PostgreSQL贸营,SQLServer吨述,Phoenix,Gauss 钞脂,ClickHouse揣云,Sybase,OceanBase冰啃,F(xiàn)irebird邓夕,Cubrid,Goldilocks阎毅,csiidb
- 達(dá)夢(mèng)數(shù)據(jù)庫焚刚,虛谷數(shù)據(jù)庫,人大金倉數(shù)據(jù)庫扇调,南大通用(華庫)數(shù)據(jù)庫矿咕,南大通用數(shù)據(jù)庫,神通數(shù)據(jù)庫狼钮,瀚高數(shù)據(jù)庫
4痴腌、框架結(jié)構(gòu)
5、代碼及文檔地址
官方地址: http://mp.baomidou.com
代碼發(fā)布地址:
文檔發(fā)布地址: https://baomidou.com/pages/24112f
二燃领、入門案例
1士聪、建表
我們使用Mysql8版本
創(chuàng)建表
CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
use `mybatis_plus`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主鍵ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
`email` varchar(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
添加數(shù)據(jù)
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');
2惶岭、導(dǎo)入依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
其中谢肾,lombok只是為了簡化我們實(shí)體類的代碼
IDEA 2020.3及以上版本已經(jīng)內(nèi)置Lombok plugin了,無需安裝插件
3蹦骑、application.yml
spring:
# 配置數(shù)據(jù)源信息
datasource:
# 配置數(shù)據(jù)源類型
type: com.zaxxer.hikari.HikariDataSource
# 配置連接數(shù)據(jù)庫信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: root
#配置mybatis日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis-Plus操作表的默認(rèn)前綴
global-config:
db-config:
table-prefix: t_
# 配置MyBatis-Plus的主鍵策略
# id-type: auto
# 配置類型別名所對(duì)應(yīng)的包
# type-aliases-package: com.zl.po
4、啟動(dòng)類
在Spring Boot啟動(dòng)類中添加@MapperScan注解区岗,掃描mapper包
package com.zl;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @date 2022-05-15
* @author ZL
*/
@SpringBootApplication
@MapperScan("com.zl.mapper")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
5略板、實(shí)體類
package com.zl.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zl
* @time 2022/5/15
*/
@Data
@TableName("t_user")
public class User {
//@TableId("uid")
private Long id;
//@TableField("user_name")
private String name;
private Integer age;
private String email;
/**
* 邏輯刪除
*/
//@TableLogic
// private Integer isDeleted;
}
6、通用Mapper接口
package com.zl.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zl.po.User;
import org.springframework.stereotype.Repository;
/**
* @author zl
* @time 2022/5/15
*/
@Repository
public interface UserMapper extends BaseMapper<User> {
}
7慈缔、測試
package com.zl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
/**
* 通用Mapper測試
*/
@SpringBootTest
class MybatisPlusTest {
@Autowired
private UserMapper userMapper;
/**
* 查詢所有
* SELECT id,name,age,email FROM user
*/
@Test
void testSelectList() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
三叮称、進(jìn)階
1、不同數(shù)據(jù)庫yml配置
Mysql
spring:
# 配置數(shù)據(jù)源信息
datasource:
# 配置數(shù)據(jù)源類型
type: com.zaxxer.hikari.HikariDataSource
# 配置連接數(shù)據(jù)庫信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: root
#配置mybatis日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis-Plus操作表的默認(rèn)前綴
global-config:
db-config:
table-prefix: t_
# 配置MyBatis-Plus的主鍵策略
# id-type: auto
# 配置類型別名所對(duì)應(yīng)的包
# type-aliases-package: com.zl.po
其中mysql8的url為:
jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
mysql5的url為:
jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false
Sqlserver
# DataSource Config
spring:
datasource:
username: sa
password: root
url: jdbc:sqlserver://localhost:1433;DatabaseName=test
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
Oracle
spring:
datasource:
driverClassName: oracle.jdbc.OracleDriver
username: root
password: root
url: jdbc:oracle:thin:@//localhost:1521/test
2藐鹤、通用Service接口
Uservice
package com.zl.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zl.po.User;
/**
* @author zl
* @time 2022/5/15
*/
public interface UserService extends IService<User> {
}
UserServiceImpl
package com.zl.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.springframework.stereotype.Service;
/**
* @author zl
* @time 2022/5/15
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
3瓤檐、通用Mapper和通用Service常規(guī)用法
package com.zl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
/**
* 通用Mapper測試
*/
@SpringBootTest
class MybatisPlusTest {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
/**
* 查詢所有
* SELECT id,name,age,email FROM user
*/
@Test
void testSelectList() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
/**
* 插入
* INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
*/
@Test
void testInsert(){
User user = new User();
user.setName("張三");
user.setAge(23);
user.setEmail("zhangsan@163.com");
int result = userMapper.insert(user);
System.out.println("受影響的行數(shù):"+result);
System.out.println("新建的ID:"+user.getId());
}
/**
* 根據(jù)ID刪除
* DELETE FROM user WHERE id=?
*/
@Test
void testDeleteById(){
int result = userMapper.deleteById(1525835539440345090L);
System.out.println("受影響的行數(shù):"+result);
}
/**
* 根據(jù)ID批量刪除
* DELETE FROM user WHERE id IN ( ? , ? )
*/
@Test
void testDeleteBatchIds(){
int result = userMapper.deleteBatchIds(Arrays.asList(1L, 2L));
System.out.println("受影響的行數(shù):"+result);
}
/**
* 根據(jù)Map刪除
* DELETE FROM user WHERE name = ? AND age = ?
*/
@Test
void testDeleteByMap(){
Map<String,Object> map = new HashMap<>();
map.put("age",21);
map.put("name","Sandy");
int result = userMapper.deleteByMap(map);
System.out.println("受影響的行數(shù):"+result);
}
/**
* 根據(jù)ID更新
* UPDATE user SET name=?, age=? WHERE id=?
*/
@Test
void testUpdateById(){
User user = new User();
user.setId(5L);
user.setName("admin");
user.setAge(33);
int result = userMapper.updateById(user);
System.out.println("受影響的行數(shù):"+result);
}
/**
* 根據(jù)ID查詢
* SELECT id,name,age,email FROM user WHERE id=?
*/
@Test
void testSelectById(){
User user = userMapper.selectById(5L);
System.out.println(user);
}
/**
* 根據(jù)ID批量查詢
* SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
*/
@Test
void testSelectByBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(3L, 5L));
users.forEach(System.out::println);
}
/**
* 根據(jù)Map查詢
* SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
*/
@Test
void testSelectByMap(){
Map<String,Object> map = new HashMap<>();
map.put("name","admin");
map.put("age",33);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
/**
* 查詢總記錄數(shù)
* SELECT COUNT( * ) FROM user
*/
@Test
void testGetCount(){
long count = userService.count();
System.out.println("總記錄數(shù):"+count);
}
/**
* 批量插入:執(zhí)行10次
* INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
*/
@Test
void testSaveBatch(){
List<User> userList = new ArrayList<>();
for (int i=0;i<10;i++){
User user = new User();
user.setName("zl" + i);
user.setAge(20 + i);
userList.add(user);
}
boolean flag = userService.saveBatch(userList);
System.out.println("插入是否成功:"+flag);
}
}
4、Wrapper常規(guī)用法
package com.zl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;
/**
* Wrapper測試
* @author zl
* @time 2022/5/15
*/
@SpringBootTest
public class MybatisPlusWrapperTest {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
/**
* 查詢用戶名包含a娱节,年齡在20到30之間挠蛉,并且郵箱不為null的用戶信息
* SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
*/
@Test
void test01(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.between("age",20,30)
.isNotNull("email");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 按年齡降序查詢用戶,如果年齡相同則按id升序排列
* SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,uid ASC
*/
@Test
void test02(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age").orderByAsc("uid");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 刪除email為空的用戶
* UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
*/
@Test
void test03(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int result = userMapper.delete(queryWrapper);
System.out.println("影響的行數(shù):"+result);
}
/**
* 將(年齡大于20并且用戶名中包含有a)或郵箱為null的用戶信息修改
* UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (age >= ? AND user_name LIKE ? OR email IS NULL)
*/
@Test
void test04(){
User user = new User();
user.setAge(10);
user.setEmail("zl@163.com");
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age",20)
.like("user_name","a")
.or()
.isNull("email");
int result = userMapper.update(user, queryWrapper);
System.out.println("受影響的行數(shù):"+result);
}
/**
* 將用戶名中包含有a并且(年齡大于20或郵箱為null)的用戶信息修改
* UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age >= ? OR email IS NULL))
*/
@Test
void test05(){
User user = new User();
user.setAge(15);
user.setEmail("zl2@163.com");
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.and(i->i.ge("age",20).or().isNull("email"));
int result = userMapper.update(user, queryWrapper);
System.out.println("受影響的行數(shù):"+result);
}
//todo 組裝select子句
/**
* 查詢用戶信息的username和age字段
* SELECT user_name,age FROM t_user WHERE is_deleted=0
*/
@Test
void test06(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("user_name","age");
//selectMaps()返回Map集合列表肄满,通常配合select()使用谴古,避免User對(duì)象中沒有被查詢到的列值為null
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);
}
/**
* 將(年齡大于20或郵箱為null)并且用戶名中包含有a的用戶信息修改
* UPDATE t_user SET age=?,email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
*/
@Test
void test07(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("age",18)
.set("email","zl@163.com")
.like("user_name","a")
.and(i->i.gt("age",20).or().isNull("email"));
int result = userMapper.update(null, updateWrapper);
System.out.println("影響行數(shù):"+result);
}
/**
* Condition條件
* SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
*/
@Test
void test08(){
//定義查詢條件,有可能為null(用戶未輸入或未選擇)
String username = null;
Integer ageBegin = 10;
Integer ageEnd = 24;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username), "username", "a")
.ge(ageBegin != null, "age", ageBegin)
.le(ageEnd != null, "age", ageEnd);
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
@Test
public void test09() {
//定義查詢條件稠歉,有可能為null(用戶未輸入)
String username = "a";
Integer ageBegin = 10;
Integer ageEnd = 24;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//避免使用字符串表示字段掰担,防止運(yùn)行時(shí)錯(cuò)誤
queryWrapper
.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
@Test
public void test10() {
//組裝set子句
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper
.set(User::getAge, 18)
.set(User::getEmail, "user@atguigu.com")
.like(User::getName, "a")
.and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail));
//lambda表達(dá)式內(nèi)的邏輯優(yōu)先運(yùn)算
User user = new User();
int result = userMapper.update(user, updateWrapper);
System.out.println("受影響的行數(shù):" + result);
}
}
5、分頁和樂觀鎖
1) 分頁
配置類-包含分頁和樂觀鎖
package com.zl.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 插件配置類-包含分頁插件怒炸、樂觀鎖
* @author zl
* @time 2022/5/16
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分頁插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加樂觀鎖插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
簡單測試--查詢所有
/**
* 分頁
* SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 LIMIT ?,?
*/
@Test
void testPage(){
//當(dāng)前頁恩敌、每頁顯示條數(shù)
Page<User> page = new Page<>(1,2);
userMapper.selectPage(page, null);
//獲取分頁數(shù)據(jù)
List<User> list = page.getRecords();
list.forEach(System.out::println);
System.out.println("當(dāng)前頁:"+page.getCurrent());
System.out.println("每頁顯示的條數(shù):"+page.getSize());
System.out.println("總記錄數(shù):"+page.getTotal());
System.out.println("總頁數(shù):"+page.getPages());
System.out.println("是否有上一頁:"+page.hasPrevious());
System.out.println("是否有下一頁:"+page.hasNext());
}
自定義分頁接口
Mapper
/**
* 根據(jù)年齡查詢用戶列表,分頁顯示
* @param page 分頁對(duì)象,xml中可以從里面進(jìn)行取值,傳遞參數(shù) Page 即自動(dòng)分頁,必須放在第一位
* @param age 年齡
* @return
*/
Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zl.mapper.UserMapper">
<!-- 當(dāng)實(shí)體類的屬性名稱和數(shù)據(jù)庫的列名不一致時(shí)横媚,需要用resultMap映射 -->
<resultMap id="UserMap" type="User">
<!-- id為主鍵 -->
<id column="id" property="id"/>
<!-- column是數(shù)據(jù)庫表的列名 , property是對(duì)應(yīng)實(shí)體類的屬性名 -->
<result column="uid" property="id"/>
<result column="user_name" property="name"/>
</resultMap>
<!--Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
<select id="selectPageVo" resultMap="UserMap">
select uid,user_name,age,email from t_user where age > #{age}
</select>
</mapper>
測試類
/**
*
* 自定義分頁接口
*/
@Test
public void testSelectPageVo(){
//設(shè)置分頁參數(shù)
Page<User> page = new Page<>(1, 2);
userMapper.selectPageVo(page, 10);
//獲取分頁數(shù)據(jù)
List<User> list = page.getRecords();
list.forEach(System.out::println);
System.out.println("當(dāng)前頁:"+page.getCurrent());
System.out.println("每頁顯示的條數(shù):"+page.getSize());
System.out.println("總記錄數(shù):"+page.getTotal());
System.out.println("總頁數(shù):"+page.getPages());
System.out.println("是否有上一頁:"+page.hasPrevious());
System.out.println("是否有下一頁:"+page.hasNext());
}
2) 樂觀鎖
數(shù)據(jù)庫表要增加一個(gè)字段version
然后用注解@Version
package com.zl.po;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
/**
* @author zl
* @time 2022/5/16
*/
@Data
public class Product {
private Long id;
private String name;
private Integer price;
@Version
private Integer version;
}
測試代碼
/**
* 樂觀鎖
*/
@Test
public void testProduct01(){
//小李查詢商品價(jià)格
Product productLi = productMapper.selectById(1);
System.out.println("小李查詢的商品價(jià)格:"+productLi.getPrice());
//小王查詢商品價(jià)格
Product productWang = productMapper.selectById(1);
System.out.println("小王查詢的商品價(jià)格:"+productWang.getPrice());
//小李將商品價(jià)格+50
productLi.setPrice(productLi.getPrice()+50);
productMapper.updateById(productLi);
//小王將商品價(jià)格-30
productWang.setPrice(productWang.getPrice()-30);
int result = productMapper.updateById(productWang);
if(result == 0){
//操作失敗纠炮,重試
Product productNew = productMapper.selectById(1);
productNew.setPrice(productNew.getPrice()-30);
productMapper.updateById(productNew);
}
//老板查詢商品價(jià)格
Product productLaoban = productMapper.selectById(1);
System.out.println("老板查詢的商品價(jià)格:"+productLaoban.getPrice());
}
6、代碼生成器
依賴
<!-- 代碼生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
測試類
package com.zl;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
/**
* @author zl
* @time 2022/5/16
*/
public class FastAutoGeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3307/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "root")
.globalConfig(builder -> {
builder.author("zl") // 設(shè)置作者
//.enableSwagger() // 開啟 swagger 模式
.fileOverride() // 覆蓋已生成文件
.outputDir("D://mybatis_plus"); // 指定輸出目錄
})
.packageConfig(builder -> {
builder.parent("com.zl") // 設(shè)置父包名
.moduleName("mybatisplus") // 設(shè)置父包模塊名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 設(shè)置mapperXml生成路徑
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 設(shè)置需要生成的表名
.addTablePrefix("t_", "c_"); // 設(shè)置過濾表前綴
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板灯蝴,默認(rèn)的是Velocity引擎模板
.execute();
}
}
7恢口、多數(shù)據(jù)源
依賴
<!-- 多數(shù)據(jù)源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
配置文件
spring:
# 配置數(shù)據(jù)源信息
datasource:
dynamic:
# 設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
primary: master
# 嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時(shí)拋異常,false使用默認(rèn)數(shù)據(jù)源
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
slave_1:
url: jdbc:mysql://localhost:3307/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.zl.po
在UserServiceImpl上加上注解@DS
package com.zl.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.springframework.stereotype.Service;
/**
* @author zl
* @time 2022/5/15
*/
//指定所操作的數(shù)據(jù)源
@DS("master")
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
8、MybatisX插件
MyBatis-Plus為我們提供了強(qiáng)大的mapper和service模板穷躁,能夠大大的提高開發(fā)效率
但是在真正開發(fā)過程中耕肩,MyBatis-Plus并不能為我們解決所有問題,例如一些復(fù)雜的SQL问潭,多表 聯(lián)查猿诸,我們就需要自己去編寫代碼和SQL語句,我們?cè)撊绾慰焖俚慕鉀Q這個(gè)問題呢狡忙,這個(gè)時(shí)候可 以使用MyBatisX插件 MyBatisX一款基于 IDEA 的快速開發(fā)插件梳虽,為效率而生。
MyBatisX插件用法:https://baomidou.com/pages/ba5b24