文章目录
- 什么是mybatisplus
- 依赖
- 入门案例
- 自动填充
- 乐观锁
- 悲观锁
- 乐观锁
- mybatisPlus实现乐观锁
- 批量查询
- 根据指定条件查询
- 分页查询
- 删除
- 物理删除
- 逻辑删除
- 逻辑删除的实现
- 性能分析插件
- MP中的复杂查询
什么是mybatisplus
mybatisplus是mybatis的增强工具,支持多种类型的数据库。
依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
补充:lombok依赖—简化实体类开发
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
在实体类上添加@Data注解即可无需再手写getter and setter 方法和toString()方法等。
入门案例
1、创建springboot项目并导入相关依赖
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2、外部属性文件中配置数据库相关属性
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/t1?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
3、创建实体类并添加注解@Data
@Data
public class User {
private Integer id;
private String name;
private String password;
}
4、创建mapper接口文件并实现BaseMapper<>接口文件
@Repository
public interface UserMapper extends BaseMapper<User> {
}
5、创建测试类并注入相关属性
@SpringBootTest
class UserMapperTest {
@Autowired
UserMapper mapper;
}
6.1、测试查询表中的所有数据
@Test
public void select(){
List<User> users = mapper.selectList(null);
users.forEach(System.out::println);
}
6.2、测试往表中插入数据
@Test
public void add(){
User user = new User();
user.setId(5);
user.setName("Mary");
user.setPassword("mary");
int i = mapper.insert(user);
}
6.3、测试根据id删除表中数据(物理删除)
@Test
public void TestDelete(){
mapper.deleteById(5);
}
6.4、测试修改表中数据
@Test
public void TestUpdate(){
User user = new User();
user.setId(5);
user.setName("Jack");
user.setPassword("Jack");
mapper.updateById(user);
}
补充:可以在外部属性文件中添加mybatis日志信息,从而在控制台看到相对应的sql语句。
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
自动填充
1、在实体类相关属性上添加@TableFiled注解,该注解有fill属性
fill属性值:
FieldFill.INSERT 执行插入语句时填充值
FieldFill.UPDATE 执行修改语句时填充值
FieldFill.INSERT_UPDATE 执行插入和修改语句时都填充值
@TableField(fill = FieldFill.INSERT)
private Date createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
2、创建类,实现接口MetaObjectHandler接口并实现里面的insertFill()和updateFill()
@Component
public class myHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createdTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
3、测试添加
@Test
public void add(){
User user = new User();
user.setId(7);
user.setName("张三");
user.setPassword("abc");
int i = mapper.insert(user);
}
运行结果:
4、测试修改
@Test
public void TestUpdate(){
User user = new User();
user.setId(7);
user.setName("李四");
user.setPassword("123");
mapper.updateById(user);
}
运行结果:
乐观锁
在事务中如果不考虑隔离问题,即会出现读问题(脏读、不可重复读、幻读),也会出现写问题(丢失更新)。针对写问题可通过悲观锁或乐观锁解决。
悲观锁
总是假设最坏的情况,每次拿数据的时候,都认为别人也会修改,所以每次都会加锁。每次只能有一个在执行。
乐观锁
乐观锁是相对悲观锁而言的,总是假设最好的情况,每次拿数据的时候,都认为别人不会修改。但是在更新数据的时候,会判断再次期间有没有人去修改这个数据,如果发现被修改了即产生了冲突,则返回给用户错误的信息,让用户决定如何去做。
mybatisPlus实现乐观锁
1、在表中添加version字段并设置默认值为0
2、在实体类中添加该属性,并在属性上添加@Version注解
@Version
private Integer version;
3、创建配置类,配置乐观锁插件
@Configuration
@MapperScan("cn.tedu.mybatisplus4.mapper")
public class myConfig {
/*配置乐观锁插件*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
4、测试,测试修改前需要先执行查询操作
@Test
public void update(){
User user = mapper.selectById(1);
user.setId(1);
user.setName("小花");
user.setPassword("1234");
mapper.updateById(user);
}
结果为:version字段值从0到1,表示进行了一次修改
批量查询
案例演示
/*批量查詢*/
@Test
public void selectAll(){
List<User> users = mapper.selectBatchIds(Arrays.asList(1, 3, 5));
users.forEach(System.out::println);
}
根据指定条件查询
案例演示:
/*根据指定条件查询*/
@Test
public void selectByName(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","张三");
map.put("password","123");
List<User> users = mapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
1、配置分页查询插件
/*分页查询插件*/
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
2、创建page对象并赋值(当前页数和每页显示记录数)
public void selectByPage(){
Page<User> page = new Page<>(1,3);
mapper.selectPage(page,null);
}
3、通过page对象获取分页数据
page.getCurrent();//获取当前页数
page.getSize();//显示的记录数
page.getTotal();//总的记录数
page.getPages();//总的页数
List<User> users = page.getRecords();//每页的记录数集合
page.hasNext();//是否有下一页
page.hasPrevious();//是否有上一页
users.forEach(System.out::println);
删除
物理删除
真实删除,把数据从数据库中删除,且无法恢复。
案例:
@Test
public void TestDelete(){
mapper.deleteById(5);
}
逻辑删除
假删除,只是把数据库中对应的字段信息改为“删除状态”,前台查询不到数据,但数据真实存在在数据库中。
逻辑删除的实现
1、在表字段中添加deleted字段,0表示未删除状态,1表示删除状态
2、在实体类中添加该属性及注解
@TableField(fill = FieldFill.INSERT)
@TableLogic
private Integer deleted;
3、配置逻辑删除插件
/*逻辑删除插件*/
@Bean
public ISqlInjector injector(){
return new LogicSqlInjector();
}
4、测试
@Test
public void TestDelete(){
mapper.deleteById(5);
}
结果为:
将字段信息修改为1,表示删除状态,且此时再次执行查询所有信息命令无法查询到此信息。
@Test
public void select(){
List<User> users = mapper.selectList(null);
users.forEach(System.out::println);
}
5、外部属性文件中配置参数信息(不配置时默认0表示未删除状态,1表示删除状态)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus.global-config.db-config.logic-delete-value=1
性能分析插件
可用于排查每句sql语句的执行效率,从而针对性进行语句优化。
1、配置性能分析插件
/*性能分析插件*/
@Bean
@Profile({"dev","test"})//设置环境开启,dev--开发环境test--测试环境prod--生产环境
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor pi = new PerformanceInterceptor();
pi.setMaxTime(200);//超过设置的最大ms数则sql语句不执行
pi.setFormat(false);//sql是否格式化,默认值也是false
return pi;
}
2、配置属性文件中的参数信息
spring.profiles.active=dev
MP中的复杂查询
QueryWrapper w = new QueryWrapper();
w.ge("id",7);//大于等于
w.gt("id",7);//大于
w.le("id",7);//小于等于
w.lt("id",7);//小于
w.eq("id",7);//等于
w.ne("id",7);//不等于
w.isNull("password");//字段为空
w.isNotNull("password");//字段不为空
w.orderByDesc("id");//根据id降序排序
w.orderByAsc("id");//根据id升序排序
w.between("id",2,6);//id值在2-6之间的
w.notBetween("id",2,6);//id值不在2-6之间的
w.like("name","小");//姓名字段包含“小”的---模糊查询
w.notLike("name","小");//姓名字段不包含“小”的---模糊查询
w.last("and name='张三'");//在sql末尾拼接该字符串
List<User> list = mapper.selectList(w);
list.forEach(System.out::println);