官网地址:
https://www.baomidou.com/
MyBatis-Plus(简称MP)好处:润物细无声,对mybatis只做增强,不做改变,简单的配置,就可对单表进行crud操作。
准备:
0.准备数据库表
1.依赖jar
2.编写配置
3.编写代码
实体类,持久层,业务层,控制层
4.运行测试
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]');
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- @RestController -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatisPlus注解使用 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
核心application.yml
spring:
datasource: #数据库连接
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///db_j2310
username: root
password: xing1688
type: com.alibaba.druid.pool.DruidDataSource
jackson: #json日期
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
application.yml
spring:
datasource: #数据库连接
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///db_j2310
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
jackson: #json日期
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mvc:
pathmatch: #Swagger相关
matching-strategy: ant_path_matcher
redis:
host: 110.40.192.129
port: 6379
password: ####
mybatis: #Mybatis的映射文件
mapper-locations: classpath:mapper/*.xml
开关类:
@SpringBootApplication
@MapperScan(basePackages = "com.qfedu.mybatisplus01.dao") //扫描
public class Mybatisplus01Application {
public static void main(String[] args) {
SpringApplication.run(Mybatisplus01Application.class, args);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_student")
public class Student {
@TableId(type = IdType.AUTO)//设置主键的自增
private Long id;
private String name;
private Integer age;
private String email;
@Version //标记这个是乐观锁的字段
private Integer version;
}
public interface UserDao extends BaseMapper<User> {
}
public interface StudentService extends IService<Student> {
}
public class StudentServiceImpl extends ServiceImpl<StudentDao,Student> {
}
package com.yd.mybatisplus01;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.mybatisplus01.dao.StudentDao;
import com.yd.mybatisplus01.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
* @author MaoXiqi
* @organization: Lucky
* @create 2023-10-09 18:57:07
* @description MyBatisplusTest2Api
*/
@Slf4j
@SpringBootTest
public class MyBatisplusTest2 {
@Resource
private StudentDao dao;
@Test
public void t1() {
log.info("查询,{}",dao.selectList(null));
}
@Test
public void t2() {
log.info("新增,{}",dao.insert(new Student(null,"张三1",19,"[email protected]",1)));
}
//条件构造器 QueryWrapper
@Test
public void t3() {
// 条件构造器 多个条件 默认采用 and
QueryWrapper<Student> wrapper = new QueryWrapper<>();
// 条件查询 在XXX之间
wrapper.like("name", "张").or().between("age", 10, 20);
log.info("条件构造器{}",dao.selectList(wrapper));
}
// 条件构造器 LambdaQueryWrapper 复习:Lambda表达式,函数式编程
@Test
public void t4() {
// 条件构造器 多个条件 默认采用 and
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
wrapper.like(Student::getName,"张").or().between(Student::getAge,10,20);
log.info("条件构造器{}",dao.selectList(wrapper));
}
@Test
public void t5() {
// 分页
Page<Student> page = new Page<>(2, 1);
Page p = dao.selectPage(page, null);
log.info("分页查询,总数据量:{},分页内容{}",p.getTotal(),p.getRecords());
}
// 测试乐观锁 修改
@Test
public void t6() {
// 每次修改,指定的乐观锁需要和数据库一致,否则修改失败
// 修改成功后,乐观锁会自动+1
Student student = new Student(3L,"李四",18,"[email protected]",1);
log.info("修改,乐观锁{}",dao.updateById(student));
}
}
MyBatisplusTest
package com.yd.mybatisplus01;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yd.mybatisplus01.dao.UserDao;
import com.yd.mybatisplus01.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
* @author MaoXiqi
* @organization: Lucky
* @create 2023-10-09 10:06:24
* @description MyBatisplusTestApi
*/
@Slf4j
@SpringBootTest
public class MyBatisplusTest {
@Resource
private UserDao dao;
@Test
public void t1(){
log.info("新增,{}",dao.insert(new User(100L,"张三",18,"[email protected]")));
}
@Test
public void t2() {
log.info("查询所有,{}",dao.selectList(null));
}
@Test
public void t3() {
log.info("查询,{}",dao.selectById(100));
}
@Test
public void t4() {
log.info("修改,{}",dao.updateById(new User(100L,"李四",19,"[email protected]")));
}
@Test
public void t5() {
log.info("删除,{}",dao.deleteById(1));
}
@Test
public void t6(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 模糊查询
wrapper.like("name", "li");
log.info("条件构造器{}",dao.selectList(wrapper));
}
}
package com.yd.mybatisplus01.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.mybatisplus01.entity.User;
import com.yd.mybatisplus01.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.models.auth.In;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* @author MaoXiqi
* @organization: Lucky
* @create 2023-10-09 11:20:02
* @description UserControllerApi
*/
@RestController
@Api(tags = "用户模块")
public class UserController {
@Resource
private UserService service;
@PostMapping("save")
public String save(@RequestBody User user) {
return service.save(user)?"新增成功":"新增失败";
}
@PostMapping("delete")
public String delete(@RequestBody Map<String, Integer> map) {
return service.removeById(map.get("id"))?"删除成功":"删除失败";
}
@PostMapping("update")
public String update(@RequestBody User user) {
return service.updateById(user)?"修改成功":"修改失败";
}
@GetMapping("all")
public List<User> all(String name) {
return service.list(new QueryWrapper<User>().like("name",name));
}
@GetMapping("page")
public Page<User> page(int page,int size,String name) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName,name).orderByDesc(User::getId);
return service.page(new Page<>(page,size),wrapper);
}
}
提升
通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus
启动时自动解析实体表关系映射转换为 Mybatis
内部对象注入容器
内置方法
// 插入一条记录
int insert(T entity);
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);
// 查询(根据ID 批量查询)
List selectBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
// 查询(根据 columnMap 条件)
List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
// 根据 Wrapper 条件,查询全部记录
List
多去使用:
重点:
1.BaseMapper<对应的实体类>
内部封装的单表的CRUD接口,我们只需要在dao层对应接口上继承就可以
2. IService<对应的实体类>
内部封装了单表的业务逻辑的方法,接口,我们可以再业务接口层继承这个接口,就拥有方法
3. ServiceImpl<对应的dao,对应的实体类>
内部对IService的方法进行了实现
4.注解
@TableName 修饰类,作用:写出类名对应的表名,不一致需要使用
@TableId(type = IdType.AUTO) 修饰属性,作用:设置主键的自增
Mybatis-Plus内部封装了条件构造器,为了方便实现条件查询,内部采用的动态SQL
Wrapper 条件构造抽象类
– AbstractWrapper 查询条件封装,用于生成 sql 中的 where 语句。
– QueryWrapper Entity对象封装操作类,可用于查询字段。
– UpdateWrapper Update条件封装操作类,用于更新。
– AbstractLambdaWrapper 使用 Lambda 表达式封装 wrapper
– LambdaQueryWrapper 使用 Lambda 语法封装条件,用于查询。
– LambdaUpdateWrapper 使用 Lambda 语法封装条件,用于更新。
详情:https://www.baomidou.com/pages/10c804/
内置方法如下所示:
方法名 | 对应SQL | 示例 |
---|---|---|
eq(R column, Object val) | = | eq(“name”, “老王”) —> name = ‘老王’ |
ne(R column, Object val); | <> | ne(“name”, “老王”) —> name <> ‘老王’ |
gt(R column, Object val); | > | gt(“name”, “老王”) —> name > ‘老王’ |
ge(R column, Object val); | >= | ge(“name”, “老王”) —> name >= ‘老王’ |
lt(R column, Object val); | < | lt(“name”, “老王”) —> name < ‘老王’ |
le(R column, Object val); | <= | le(“name”, “老王”) —> name <= ‘老王’ |
between(R column, Object val1, Object val2) | between a and b | between(“age”, 18, 30) —> age between 18 and 30 |
notBetween(R column, Object val1, Object val2); | not between a and b | notBetween(“age”, 18, 30) —> age not between 18 and 30 |
in(R column, Object… values); | IN (v0, v1, …) | in(“age”,{1,2,3}) —> age in (1,2,3) |
notIn(R column, Object… values); | NOT IN (v0, v1, …) | notIn(“age”,{1,2,3}) —> age not in (1,2,3) |
inSql(R column, Object… values); | IN (sql 语句) | inSql(“id”, “select id from table where id < 3”) —> id in (select id from table where id < 3) |
notInSql(R column, Object… values); | NOT IN (sql 语句) | |
like(R column, Object val); | LIKE ‘%值%’ | like(“name”, “王”) —> name like ‘%王%’ |
notLike(R column, Object val) | NOT LIKE ‘%值%’ | notLike(“name”, “王”) —> name not like ‘%王%’ |
likeLeft(R column, Object val) | LIKE ‘%值’ | likeLeft(“name”, “王”) —> name like ‘%王’ |
likeRight(R column, Object val) | LIKE ‘值%’ | likeRight(“name”, “王”) —> name like ‘王%’ |
isNull(R column) | IS NULL | isNull(“name”) —> name is null |
isNotNull(R column); | IS NOT NULL | isNotNull(“name”) —> name is not null |
groupBy(R… columns) | GROUP BY | groupBy(“id”, “name”) —> group by id,name |
having(String sqlHaving, Object… params) | HAVING ( sql语句 ) | having(“sum(age) > {0}”, 11) —> having sum(age) > 11 |
orderByAsc(R… columns) | ORDER BY 字段, … ASC | orderByAsc(“id”, “name”) —> order by id ASC,name ASC |
orderByDesc(R… columns); | ORDER BY 字段, … DESC | orderByDesc(“id”, “name”) —> order by id DESC,name DESC |
or(); | a or b | eq(“id”,1).or().eq(“name”,“老王”) —> id = 1 or name = ‘老王’ |
or(Consumer consumer) | or嵌套 | or(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> or (name = ‘李白’ and status <> ‘活着’) |
and(Consumer consumer) | and嵌套 | and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> and (name = ‘李白’ and status <> ‘活着’) |
nested(Consumer consumer); | 普通嵌套 | nested(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> (name = ‘李白’ and status <> ‘活着’) |
apply(String applySql, Object… params); | 拼接sql | apply(“date_format(dateColumn,‘%Y-%m-%d’) = {0}”, “2008-08-08”) —> date_format(dateColumn,‘%Y-%m-%d’) = ‘2008-08-08’") |
last(String lastSql) | 无视优化规则直接拼接到 sql 的最后 | |
exists(String existsSql) | 拼接 exists 语句 | exists(“select id from table where age = 1”) —> exists (select id from table where age = 1) |
QueryWrapper | ||
select(String… sqlSelect) | 用于指定查询需要返回的字段 | select(“id”, “name”, “age”) —> select id, name, age |
select(Predicate predicate); | 通过Lambda 表达式,过滤需要的字段 | |
lambda(); | 返回一个 LambdaQueryWrapper对象 | |
UpdateWrapper | ||
set(String column, Object val); | set 字段值 | set(“name”, null) —> set name = null |
setSql(String sql); | setSql(“name = ‘老李头’”) —> set name = ‘老李头’ | |
lambda(); | 返回一个 LambdaUpdateWrapper对象 |
重点:
QueryWrapper
LambdaQueryWrapper
//条件构造器 QueryWrapper
@Test
public void t3(){
//条件构造器 多个条件 默认采用 and
QueryWrapper<Student> wrapper=new QueryWrapper<>();
//模糊查询 在xxx之间
wrapper.like("name","2").or().between("age",20,30);
log.info("条件构造器{}",dao.selectList(wrapper));
}
//条件构造器 LambdaQueryWrapper 复习:Lambda表达式,函数式编程
@Test
public void t4(){
//条件构造器 多个条件 默认采用 and
LambdaQueryWrapper<Student> wrapper=new LambdaQueryWrapper<>();
wrapper.like(Student::getName,"2").or().between(Student::getAge,10,20);
log.info("条件构造器{}",dao.selectList(wrapper));
}
源码地址:
https://gitee.com/zheng-yida-10/my-batisplus01