CURD:增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)
MyBatis-Plus是MyBatis的增强工具,在MyBatis基础上只做增强,不做改变
作用:为了简化开发,提高效率
MyBatis-Plus的首次使用
1.创建数据库,创建数据表
# 创建数据库
create database practice character set utf8;
# 创建User表
create table User(
//测试主键策略
id bigint(20) primary key,
name varchar(30) null default null,
age int(11) null default null,
email varchar(50) null default null,
//测试自动填充
create_time datatime null default null,
update_time datatime null default null,
//测试乐观锁
version int null default null,
//测试逻辑删除
status int null default null
)
# 添加数据
insert into User (id,name,age,email) values
(1,'Jane',10,'test1@163.com',null),
(2,'Jack',20,'test2@163.com',null),
(3,'Tom',26,'test3@163.com',null),
(4,'Sandy',21,'test4@163.com',null),
(5,'Billie',24,'test5@163.com',null)
2.创建springboot项目工程
file - - new - - project - - Spring Initializr - - Java Version:8 - - Spingboot依赖随便选一个版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- 到pom.xml中修改Springboot的依赖版本 -->
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
3.引入和mp相关的依赖
pom.xml
<!--junit测试类依赖-->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<!--mybatis-plus的依赖-->
<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>
</dependency>
<!--安装lombok插件,settings——plugins——搜索lombok——安装-->
<!--lombok依赖,简化实体类,可以不需要手动生成get、set等方法,通过注解@Data来实现-->
<!-- https://blog.csdn.net/zhangmiaoping23/article/details/105707428/ -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
4.配置数据库
application.properties:在src/main/resources/application.properties中配置数据库信息
# mysql数据库连接
# 1.spring boot2.0版本(内置jdbc5驱动)
# spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
# spring.datasource.username=root
# spring.datasource.password=root123
# 2.spring boot2.1及以上版本(内置jdbc8驱动)(driver和url的变化)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# serverTimezone=GMT%2B8为时区
spring.datasource.url=jdbc:mysql://localhost:3306/practice?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root123
# 查看sql输出日志(mybatis日志) 为了查看mybaits-plus执行select的底层逻辑
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
5.编写核心代码
①.实体类
# com.atguigu.demomptest.entity.User
//@Data是lombok生成的注解,会将get、set方法和string方法都自动生成,可以点开左边的Structure查看
@Data
public class User {
//ASSIGN_ID雪花算法,分布式ID生成器,按照时间自增排序
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private Integer age;
private String email;
//INSERT,添加时自动填充值
@TableField(fill= FieldFill.INSERT)
private Date createTime; //create_time
//INSERT_UPDATE,修改时自动填充值(添加时没有值,修改时才设置值)
@TableField(fill=FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
//实现乐观锁
@Version
@TableField(fill= FieldFill.INSERT) //添加一个默认值
private Integer version;
//实现逻辑删除
@TableLogic
@TableField(fill=FieldFill.INSERT)
private Integer status;
}
②.接口
# com.atguigu.demomptest.mapper.UserMapper
//BaseMapper里面封装了增删改查等操作,泛型类为User
@Repository
public interface UserMapper extends BaseMapper<User>{}
③.启动类
# com.atguigu.demomptest.DemomptestApplication
@SpringBootApplication
// 将其放到config.MpConfig配置类中
// 因为UserMapper要动态生成它的实现类对象,动态生成对象默认查找不到,所以使用Mapper扫描来查找
// @MapperScan("com.atguigu.demomptest.mapper")
public class DemomptestApplication {
public static void main(String[] args) {
SpringApplication.run(DemomptestApplication.class, args);
}
}
④.Mybatis-plus的配置类
# com.atguigu.demomptest.config.MpConfig
// Mybatis-plus的配置类
// 说明这是一个配置类的注解
@Configuration
// 因为UserMapper要动态生成它的实现类对象,动态生成对象默认查找不到,所以使用Mapper扫描来查找
@MapperScan("com.atguigu.demomptest.mapper")
public class MpConfig {
/*配置乐观锁的插件*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
/* 配置分页查询的插件 */
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
⑤.自动填充处理类
# com.atguigu.demomptest.handler.MyMetaObjectHandler
//把这个类交给spring管理
//@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,标识为一个Bean
@Component
//实现MetaObjectHandler接口,并重写insertFill和updateFill两个方法
public class MyMetaObjectHandler implements MetaObjectHandler {
// 添加时自动填充值,到创建时间和修改时间中,初始修改时间就是第一次创建时的时间
@Override
public void insertFill(MetaObject metaObject) {
//setFieldValByName是设置属性值根据名字
//第一个参数:被填充实体类的字段名
//第二个参数:填充的值
//第三个参数:metaObject对象
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
//version默认值设置为1
this.setFieldValByName("version",1,metaObject);
//status在添加时自动填充默认为0,未被删除状态(1是被删除状态)
this.setFieldValByName("status",0,metaObject);
}
// 修改时自动填充值
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
⑥.测试类(**重要,实现增删改查)
# com.atguigu.demomptest/DemommptestApplicationTests
//给指定的字段或方法注入所需的外部资源
@Autowired
private UserMapper userMapper; //这里会报错,原因是实现类是动态生成的,如果想不报错在UserMapper上加一个@Repository注解
# 增
@Test
public void testadd(){
User user=new User();
//没有设置id属性主键自增长,但mybatis-plus会使用主键策略自动生成id值
user.setName("lucy");
user.setAge(18);
user.setEmail("licy@163.com");
int insert=userMapper.insert(user);
System.out.println(insert);
}
# 删
//根据id删除
@Test
public void testDeleteById(){
int rows=userMapper.deleteById(1L);
System.out.println(rows);
}
//批量删除
@Test
public void testDeleteByIds(){
int rows=userMapper.deleteBatchIds(Arrays.asList(2,3));
System.out.println(rows);
}
//简单条件删除
@Test
public void testDeleteByIf(){
Map<String,Object> map=new HashMap();
map.put("name","Lily");
map.put("age",19);
int rows=userMapper.deleteByMap(map);
System.out.println(rows);
}
//物理删除:真实删除,将数据从数据库中删除
//逻辑删除:假删除,方便删除之后的数据恢复,被删除记录的status字段被修改为“被删除状态”
//逻辑删除
//在表中添加一个status字段,作为删除的标准,每次删除时,修改标志位,0代表没有删除,1代表删除
//UPDATE user SET status=1 WHERE id=? AND status=0 查询条件有一个status=0,即查询的都是没有被删除过的记录,被删除过的记录就不会被查询出来了
@Test
public void testDeleteByLogic(){
int rows=userMapper.deleteById(1441596779656179713L); //在做了逻辑删除的配置后,再使用id进行删除,执行的语句变成了修改id=?并且status为0的记录,如果status原来就是1(被删除过了),也不会再被删除,
System.out.println(rows);
}
# 改
//update user set name=? where id=?
@Test
public void testupdate(){
User user=new User();
//需要将数字后面加一个L
user.setId(1441402736913481729L);
user.setName("Lily");
int count=userMapper.updateById(user);
System.out.println(count);
}
# 查
//查询出一个集合
@Test
public void findAll() {
List<User> users=userMapper.selectList(null);
System.out.println(users);
}
// 多个id的批量查询
// 使用selectBatchIds方法,传入一个id集合
// List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> var1);
// SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? )
// 问题:selectBatchIds怎么能确定查询的是id
@Test
public void testSelectByids(){
List<User> users=userMapper.selectBatchIds(Arrays.asList(1,2,3));
System.out.println(users);
}
// 简单的条件查询 简单了解,一般条件查询使用条件构造器来查询
// 使用selectByMap方法,使用Map来存要传的参数
// List<T> selectByMap(@Param("cm") Map<String, Object> var1);
// SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ?
@Test
public void testSelectByif(){
Map<String,Object> columnMap =new HashMap<>();
columnMap.put("name","Jack");
columnMap.put("age",20);
List<User> users=userMapper.selectByMap(columnMap);
System.out.println(users);
}
// 分页查询selectPage 也可以使用selectMapsPage进行分页查询,但是不常用
// 需要在MpConfig配置分页查询的插件
@Test
public void testselectPage(){
// 引入mybatisplus的Page依赖
// 传入2个参数,第一个是当前第几页,第二个是每页显示多少条记录
Page<User> page=new Page(1,3); //SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?
Page<User> userPage=userMapper.selectPage(page,null);
//返回对象得到分页所有数据
long pages=userPage.getPages(); //总页数 3页 SELECT COUNT(1) FROM user
long current =userPage.getCurrent(); //当前页 第1页
long total=userPage.getTotal(); //表中的总记录条数 9条数据
List<User> users=userPage.getRecords(); //当前页数据集合(3条)
boolean hasNext=userPage.hasNext(); //判断当前页是否有下一页 true
boolean hasPrevious=userPage.hasPrevious(); //判断当前页是否有上一页 false(第1页每页上一页)
System.out.println(pages);
System.out.println(current);
System.out.println(total);
System.out.println(users);
System.out.println(hasNext);
System.out.println(hasPrevious);
}
//使用MyBatis-Plus的条件构造器实现一些复杂的查询操作
@Test
public void testWrapper(){
//构造一个条件构造器对象
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//1.ge(大于等于) | gt(大于) | le(小于等于) | lt(小于) | isNull(为空) | isNotNull(不为空)
//queryWrapper.ge("age",19);
//2.eq(等于) | ne(不等于)
//queryWrapper.eq("age",19);
//3.between(在某个范围) | notBetween(不在某个范围)
queryWrapper.between("age",19,22);
//4.like(查出所有包含L的记录,like "%L%") | notLike(所有不包含L的实体记录 not like "%L%")
// likeLeft(like "L%",所有左边包含L的记录) | likeRight(like "%L",所有右边包含L的记录)
//queryWrapper.likeRight("name","L");
//queryWrapper.notLike("name","L");
//5.orderBy | orderByDesc(降序排列) | orderByAsc(升序排列)
//根绝id升序排列
queryWrapper.orderByAsc("id");
//传入条件构造器
List<User> users=userMapper.selectList(queryWrapper);
System.out.println(users);
}
# 测试乐观锁
@Test
public void testOptimisticLocker(){
//根据id查询
User user=userMapper.selectById(1441561265146171394L);
//修改
user.setName("张三");
//这里不需要手动设置version值,因为mybatis-plus会自动将version值+1
//UPDATE user SET name=?, age=?, email=?, create_time=?, update_time=?, version=? WHERE id=? AND version=?
userMapper.updateById(user);
}
6.底层逻辑
7.小节
增加
主键策略:ASSIGN_ID雪花算法,分布式ID生成器,按照时间自增排序生成主键ID值
删除
物理删除和逻辑删除:在表中添加一个status字段,删除其实是update status=1
根据id删除:deleteById
批量删除:deleteBatchIds
简单条件删除:deleteByMap
修改
自动填充:@TableField(fill= FieldFill.INSERT|INSERT_UPDATE)
乐观锁:@Version,解决丢失修改的问题
查询
查询出一个集合:selectList
多个id的批量查询: selectBatchIds
简单的条件查询:selectByMap
分页查询selectPage:selectPage
使用MyBatis-Plus的条件构造器实现一些复杂的查询操作:QueryWrapper