文章目录
一. 环境
JDK 1.8 + Maven 3.5 + SpringBoot 2.2.5 + MySQL 5.7 + IDEA 2018.3
二. 简介
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
三. 项目目录
四. 相关配置及简单测试
1. 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.mp</groupId>
<artifactId>itcast-mp-springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</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>
<version>1.18.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- mybatis-plus的springboot支持 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
2. 编写application.properties
spring.application.name=itcast-mp-springboot
# 配置数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp_crud?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
# 配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-no-delete-value=0
3. 编写实体类
package cn.itcast.mp.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 20:28 2020/3/17
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_employee")
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
private Integer age;
}
4. 编写Mapper
package cn.itcast.mp.mapper;
import cn.itcast.mp.pojo.Employee;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 20:29 2020/3/17
*/
public interface EmployeeMapper extends BaseMapper<Employee> {
}
5. 编写启动类
package cn.itcast.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 20:31 2020/3/17
*/
@MapperScan("cn.itcast.mp.mapper") //设置mapper接口的扫描包
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
6. 编写测试用例
package cn.itcast.mp;
import cn.itcast.mp.mapper.EmployeeMapper;
import cn.itcast.mp.pojo.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 20:33 2020/3/17
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestMyBatisSpringBoot {
@Autowired
private EmployeeMapper employeeMapper;
@Test
public void testSelectList(){
List<Employee> employeeList = this.employeeMapper.selectList(null);
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
}
7. 测试结果
Employee(id=1, lastName=Tom, email=tom@163.com, gender=1, age=22)
Employee(id=2, lastName=Tim, email=tim@163.com, gender=1, age=23)
Employee(id=3, lastName=Candy, email=candy@163.com, gender=0, age=18)
Employee(id=4, lastName=White, email=white@163.com, gender=0, age=28)
Employee(id=5, lastName=Black, email=black@163.com, gender=1, age=35)
五. 通用CRUD之插入操作
为id属性增加注解,即id根据数据库自增
@TableId(type = IdType.AUTO)
package cn.itcast.mp.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 20:28 2020/3/17
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_employee")
public class Employee {
@TableId(type = IdType.AUTO)
private Integer id;
private String lastName;
private String email;
private Integer gender;
private Integer age;
}
方法用例:
int insert(T entity);
实现用例:
package cn.itcast.mp;
import cn.itcast.mp.mapper.EmployeeMapper;
import cn.itcast.mp.pojo.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 21:23 2020/3/18
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestEmployee {
@Autowired
private EmployeeMapper employeeMapper;
@Test
public void TestInsert(){
Employee employee = new Employee();
employee.setAge(20);
employee.setEmail("test@163.com");
employee.setGender(1);
employee.setLastName("Green");
int result = employeeMapper.insert(employee); //result为受影响的行数
System.out.println("result =>" + result); //输出返回结果
System.out.println("id =>" + employee.getId()); //自增后的id回填到对象中
}
}
测试结果
[main] [cn.itcast.mp.TestEmployee] - [INFO] Started TestEmployee in 2.755 seconds (JVM running for 5.131)
[main] [com.zaxxer.hikari.HikariDataSource] - [INFO] root - Starting...
[main] [com.zaxxer.hikari.HikariDataSource] - [INFO] root - Start completed.
result =>1
id =>6
[SpringContextShutdownHook] [com.zaxxer.hikari.HikariDataSource] - [INFO] root - Shutdown initiated...
[SpringContextShutdownHook] [com.zaxxer.hikari.HikariDataSource] - [INFO] root - Shutdown completed.
Process finished with exit code 0
六. 通用CRUD之更新操作
1.根据id进行更新
方法用例:
int updateById(@Param(“et”) T entity);
实现用例:
@Test
public void TestUpdateById(){ //根据id更新对象
Employee employee = new Employee();
employee.setId(1);
employee.setAge(18);
employee.setEmail("666@163.com");
int result = employeeMapper.updateById(employee);
System.out.println("result =>" + result); //返回受影响行数
}
2.根据条件进行更新,使用QueryWrapper或者UpdateWrapper进行更新
方法用例:
int update(@Param(“et”) T entity, @Param(“ew”) Wrapper updateWrapper);
实现用例:
@Test
public void TestUpdate(){
//设置更新字段
Employee employee = new Employee();
employee.setAge(18);
employee.setEmail("333@163.com");
//更新条件
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id",1);
//执行更新操作
int result = employeeMapper.update(employee, queryWrapper);
System.out.println(result);
}
@Test
public void TestUpdate2(){
//设置更新条件
UpdateWrapper<Employee> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("gender",0).set("last_name","Curry")
.eq("id",1);
//执行更新操作
int result = employeeMapper.update(null, updateWrapper);
System.out.println(result);
}
七. 通用CRUD之删除操作
1.根据id删除对象
方法用例:
int deleteById(Serializable id);
实现用例:
@Test
public void TestDeleteById(){
int result = employeeMapper.deleteById(6);
System.out.println("result =>" + result);
}
2.根据map条件,删除记录
方法用例:
int deleteByMap(@Param(“cm”) Map<String, Object> columnMap);
实现用例:
@Test
public void TestDeleteByMap(){
Map<String,Object> map = new HashMap<>();
map.put("last_name","Curry");
map.put("gender",0);
//根据map进行删除,多条件之间是and
int result = employeeMapper.deleteByMap(map);
System.out.println("result =>" + result);
}
3.根据包装对象,删除记录
方法用例:
int delete(@Param("ew") Wrapper<T> wrapper);
实现用例:
@Test
public void TestDelete(){
Employee employee = new Employee();
employee.setLastName("Black");
QueryWrapper<Employee> wrapper = new QueryWrapper<>(employee);
//根据包装对象删除
int result = employeeMapper.delete(wrapper);
System.out.println("result =>" + result);
}
4.根据id集合,批量删除记录
方法用例:
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
实现用例:
@Test
public void TestDeleteBatchIds(){
//执行批量删除数据
int result = employeeMapper.deleteBatchIds(Arrays.asList(3, 4));
System.out.println("result =>" + result);
}
八. 通用CRUD之查询操作
1.根据id查询对象
方法用例:
T selectById(Serializable id);
实现用例:
@Test
public void TestSelectById(){
//根据id查询数据
Employee employee = employeeMapper.selectById(1);
System.out.println(employee);
}
2.根据id批量查询数据
方法用例:
List selectBatchIds(@Param(“coll”) Collection<? extends Serializable> idList);
实现用例:
@Test
public void TestSelectBatchIds(){
//根据id批量查询数据
List<Employee> list = employeeMapper.selectBatchIds(Arrays.asList(1, 2, 3, 4));
for (Employee employee : list) {
System.out.println(employee);
}
}
3.根据条件查询数据,只能返回一条数据,若查询到多条数据则抛出异常
方法用例:
T selectOne(@Param("ew") Wrapper<T> queryWrapper);
实现用例:
@Test
public void TestSelectOne(){
//查询条件
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("last_name","Candy");
Employee employee = employeeMapper.selectOne(wrapper);
System.out.println(employee);
}
4.根据条件查询数据,返回符合条件的数据条数
方法用例:
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
实现用例:
@Test
public void TestSelectCount(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.gt("age",18); //查询年龄大于18的数据条数
Integer count = employeeMapper.selectCount(wrapper);
System.out.println("count => " + count);
}
5.根据条件查询数据,返回数据集合
方法用例:
List selectList(@Param(“ew”) Wrapper queryWrapper);
实现用例:
@Test
public void TestSelectList(){
//设置查询条件
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("email","@163.com");
//输出查询结果
List<Employee> list = employeeMapper.selectList(wrapper);
for (Employee employee : list) {
System.out.println(employee);
}
}
6.分页查询,可设置查询条件
配置分页插件:
package cn.itcast.mp;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 15:47 2020/3/19
*/
@MapperScan("cn.itcast.mp.mapper") //设置mapper接口的扫描包
@Configuration
public class MybatisPlusConfig {
@Bean // 配置分页插件
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
方法用例:
<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
实现用例:
@Test
public void TestSelectPage(){ //测试分页查询
Page<Employee> page = new Page<>(2,1); //查询第几页,查询几条数据
//设置查询条件
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("email","@163.com");
IPage<Employee> iPage = employeeMapper.selectPage(page,wrapper);
System.out.println("数据总条数:" + iPage.getTotal());
System.out.println("数据总页数:" + iPage.getPages());
System.out.println("当前页数:" + iPage.getCurrent());
System.out.println("当前页数目:" + iPage.getSize());
List<Employee> records = iPage.getRecords();
for (Employee record : records) {
System.out.println(record);
}
}
输出结果:
数据总条数:5
数据总页数:5
当前页数:2
当前页数目:1
Employee(id=2, lastName=Tim, email=tim@163.com, gender=1, age=23)
九. 关于@TableFile注解
在Mybatis-plus中使用@TableFile注解可以指定字段的一些属性,如下:
- 对象中的属性名和字段名不一致(非驼峰)
- 对象中的属性在表中不存在
- 字段不加入查询
使用
@TableField(select = false) //查询时不返回该字段的值
private Integer gender;
@TableField(value = "age") //指定数据库表中的字段名
private Integer ageeee;
@TableField(exist = false) //在数据库中不存在的字段
private String address;
十. 自动填充
创建时间和修改时间,这些操作应该是自动完成的,不需要手动更新。
方法一:数据库级别
方法二:代码级别(建议使用)
@TableField(fill = FieldFill.INSERT) //添加自动填充字段
private Date createTime;
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
添加handler类
package cn.itcast.mp.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @Author: Ryan
* @Description:
* @Date: Create in 21:16 2020/3/19
*/
@Slf4j
@Component
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);
}
}
测试用例:
@Test
public void TestDelete2(){
Employee employee = new Employee();
employee.setId(2);
employee.setLastName("JavaNiuBi");
employeeMapper.updateById(employee);
}
运行结果:
十一. 逻辑删除
物理删除:从数据库上直接删除数据
逻辑删除:在数据库没有删除,而是通过一个变量让数据失效 deleted = 0 ====> deleted = 1
实体类添加字段:
@TableLogic //逻辑删除
private Integer deleted;
配置组件:
@Bean // 逻辑删除组件 (3.1.1开始不再需要这一步):
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-no-delete-value=0
测试方法:
//逻辑删除(在数据库中没有删除,而是通过一个变量让它失效!deleted = 0 => deleted =1)
//管理员可以查看被删除的记录!防止记录的丢失,类似于回收站
//数据库中增加deleted字段,默认值为0,即没有删除
@Test
public void TestDelete2(){
employeeMapper.deleteById(2);
}
使用的是更新操作,通过更新deleted字段将数据进行逻辑删除
结果如下:
十二. 总结
以上是MyBatis-Plus的基本使用
详细使用请查看:MyBatis-Plus 官网