官网:https://mp.baomidou.com/guide
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--mybatis plus相关(不能跟Mybatis同时导入)-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!-- lombok(前提IDEA有对应插件) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
spring:
datasource:
platform: mysql
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis?useSSl=true&userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
driver-class-name: com.mysql.jdbc.Driver
server:
port: 8080
建立对应包结构
以及官方给出的数据库测试数据,自行配备数据库:
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]');
编写类测试
POJO:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private int age;
private String name;
private String email;
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mybatisplus.Pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
//继承BaseMapper实现其中的方法
@Repository
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
至于BaseMapper中存在着什么方法直接点进去下载源码查看即可,注释都是中文
测试类方法:
import com.mybatisplus.Mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MybatisplusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
System.out.println(userMapper.selectById(1));
}
}
配置日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus默认生成id值探究
test方法:
@Test
void test01(){
User user = new User();
user.setName("jaz");
user.setAge(1);
user.setEmail("[email protected]");
int i = userMapper.insert(user);
System.out.println("受影响的行数"+i);
System.out.println("id会回填"+user);
}
发现id自动回填了一个0,但这是不合理的,因为按常理应该自动回填一个很长的复杂数字。
因此去修改实体类中的id类型,将int修改为long
再次执行并查看日志
雪花算法
雪花算法(SnowFlake)是Twitter分布式id生成算法,mybatis-plus中生成id的方式即为雪花算法。
构成:1位标识部分,41位时间戳部分,10位节点部分,12位序列号部分。
主键策略
更新 updateById(User entity)
@Test
public void testupdate(){
//测试更新,会根据条件自动拼接动态sql
User user = new User();
user.setId((long) 0);
user.setName("jaz1");
user.setAge(99);
user.setEmail("[email protected]");
userMapper.updateById(user);
}
自动填充
即gmt_create(数据创建时间)和gmt_modified(数据修改时间)字段,以供后续的数据追踪。
添加字段:gmt_create,gmt_modified
同步实体类
添加相关注解:
//id策略规则
@TableId(type = IdType.ID_WORKER)
private Long id;
private int age;
private String name;
private String email;
//填充
@TableField(fill = FieldFill.INSERT)
private Date gmt_create;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmt_modified;
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.time.LocalDateTime;
import java.util.Date;
@Slf4j
@Component
public class FieldFillHandler implements MetaObjectHandler {
//插入时填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("gmt_create",new Date(),metaObject);
this.setFieldValByName("gmt_modified",new Date(),metaObject);
}
//更新时填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("gmt_create",new Date(),metaObject);
this.setFieldValByName("gmt_modified",new Date(),metaObject);
}
}
乐观锁,悲观锁
乐观锁:无论干什么都不会加锁,如果出问题则重新更新值测试
悲观锁:无论干什么总是会加锁
乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
使用,首先在数据库添加version字段,默认值先为1
补充实体类
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@MapperScan("com.mybatisplus.Mapper")
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
对应的测试类:
@Test
public void testupdate1(){
User user1 = userMapper.selectById(0);
user1.setName("jaz2232");
user1.setAge(99);
user1.setEmail("[email protected]");
userMapper.updateById(user1);
}
更新时会自动查询version
然后对应的version会自动递增
查询操作
//测试查询
@Test
public void testSelect(){
//根据id查询用户
User user = userMapper.selectById(0);
System.out.println(user);
//根据id查询批量用户
List<User> user1 = userMapper.selectBatchIds(Arrays.asList(1,2,3));
user1.forEach(System.out::println);
//条件查询
HashMap<String, Object> map = new HashMap<>();
//自定义查询条件
map.put("name","Jack");
List<User> users = userMapper.selectByMap(map);
System.out.println("条件查询");
users.forEach(System.out::println);
}
删除操作
测试类:
@Test
public void testdelete(){
//根据id删除
userMapper.deleteById(0);
//批量删除
userMapper.deleteBatchIds(Arrays.asList(1,2,3));
//map删除
HashMap<String, Object> map = new HashMap<>();
map.put("name","Jack");
map.put("age",17);
userMapper.deleteByMap(map);
}
逻辑删除
数据库中增加字段isdelete,0为没有删除,1为已经删除
实体类中丰富字段:
package com.mybatisplus.Pojo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
//id策略规则
@TableId(type = IdType.ID_WORKER)
private Long id;
private int age;
private String name;
private String email;
//填充
@TableField(fill = FieldFill.INSERT)
private Date gmt_create;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmt_modified;
@Version
private Integer version;
@TableLogic //逻辑删除
private Integer isdelete;
}
配置逻辑删除Bean组件:
//逻辑删除
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector() ;
}
application.yml 加入配置:
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
userMapper.deleteById((long)0);
可以看到现在的删除操作实际上是更新操作,且isdelete为1的用户也不会被select语句查询到
在MyBatisPlusConfig配置文件中注册分页插件
//注册分页查询组件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor() ;
}
测试类:
@Test
public void testPage(){
//current当前页,size大小
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page,null);
System.out.println("获取数据总数"+page.getTotal());
System.out.println("获取数据大小"+page.getSize());
}
mybatisplus提供的性能分析插件可以帮助处理慢sql,即此sql语句运行的时间超过自定义的限定值则直接停止执行该sql语句
//性能分析插件
@Bean
@Profile({
"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);//设置sql执行的最大时间为100毫秒
performanceInterceptor.setFormat(true);//格式化支持
return performanceInterceptor;
}
方法 | 使用说明 |
---|---|
isNotNull | 字段不为空 |
ge | 大于指定值 |
le | 小于指定值 |
eq | 等于指定值 |
like | 模糊查询包含指定字符 |
notLike | 模糊查询不包含指定字符 |
likeRight | 模糊查询以**开头 |
likeLeft | 模糊查询以**结尾 |
@Test
public void test1(){
//查询name不为空且邮箱不为空且年龄大于22岁的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",22);
userMapper.selectList(wrapper).forEach(System.out::println);
}
@Test
public void test2(){
//查询name为Jack的一个用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.eq("name","Jack");
System.out.println(userMapper.selectOne(wrapper));
}
@Test
public void test3(){
//查询年龄在22-25岁之间的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.between("age",22,25);
Integer count = userMapper.selectCount(wrapper);
System.out.println(count);
}
@Test
public void test4(){
//模糊查询名字中带有J字母的
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.like("name","J");
userMapper.selectList(wrapper).forEach(System.out::println);
}
@Test
public void test5(){
//模糊查询名字中不带有J字母的,邮箱以2为开头且以com为结尾的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.notLike("name","9")
.likeRight("email","t") //邮箱是以2开头的
.likeLeft("email","com");
userMapper.selectList(wrapper).forEach(System.out::println);
}
参考:
https://segmentfault.com/a/1190000013703649
https://github.com/souyunku/SnowFlake
https://space.bilibili.com/95256449?spm_id_from=333.788.b_765f7570696e666f.1