mybatis-plus基础知识
视频地址:mybatis-plus
文章目录
特性
版本version配置
@Slf4j
@Component
public class MyMetaHandler implements MetaObjectHandler {
// 插入时的策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start inserfill...");
this.setFieldValByName("create_time",new Date(),metaObject);
this.setFieldValByName("update_time",new Date(),metaObject);
this.setFieldValByName("version",1,metaObject);
}
//更新时的策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start updatefill...");
this.setFieldValByName("update_time",new Date(),metaObject);
}
}
实体类配置
package com.hjx.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import java.util.Date;
/**
* mapper_user映射 mapper.xml中的resultMap
* 注意:
*/
@Data
@TableName(value = "user",resultMap = "mapper_user")
public class User extends Model<User>{
@TableId(value = "id",type = IdType.AUTO)
private int id;
// exist = true:标识改字段和数据库字段关联
@TableField(exist = true)
private String userName;
private String passWord;
// 设置字段填充
@TableField(fill = FieldFill.INSERT )
private Date create_time;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date update_time;
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
// 逻辑删除
@TableLogic
private int deleted;
}
快速入门
1.连接数据库
2.pojo类
3.新建mapper包并新建一个mapper接口,如下:
package com.example.mybatisplus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mybatisplus.pojo.User;
// 继承BaseMapper接口即可
public interface UserMapper extends BaseMapper<User> {
}
4.在主启动类上开启注解扫描
4.测试
package com.example.mybatisplus;
import com.example.mybatisplus.mapper.UserMapper;
import com.example.mybatisplus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
// 查询所有数据
public void user_Test() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}
mybatis与mybatis-plus的区别
配置日志的输出
插入测试及雪花算法
主键生成策略
默认ID_WORKER (全局唯一id)
这里mybatis-plus使用的是雪花算法
雪花算法
主键自增
1.需要将数据库的id字段设为自增
2.在实体类id字段上配置注解@TableId(type = IdType.AUTO)
几种不同的主键自增策略
AUTO(0), // id自增
NONE(1), // 未设置主键自增策略
INPUT(2), // 手动输入
ASSIGN_ID(3), //
ASSIGN_UUID(4), //
/** @deprecated */
@Deprecated
ID_WORKER(3), // 默认的全局唯一id
/** @deprecated */
@Deprecated
ID_WORKER_STR(3), // 全局唯一表示法 截取字符串
/** @deprecated */
@Deprecated
UUID(4); // 全局唯一id
更新操作
@Test
public void updateData(){
User user=new User();
user.setUser("yang yang");
user.setAge(23);
user.setPass("123");
user.setSex("man");
user.setId(6);
// 注意:这里的updateById方法的参数是一个对象
int count=userMapper.updateById(user);
System.out.println(count);
}
自动填充
数据库级别
代码级别
编写处理器来处理注解
这样的话,在执行插入和更新操作时,会将数据的updateTime和inserTime字段的值进行自动插入和更新
/*
如果不想每次都写private
final Logger logger = LoggerFactory.getLogger(当前类名.class); 可以用注解@Slf4j;
* */
@Slf4j
@Component
public class MyMetaHandler implements MetaObjectHandler {
// 插入时的策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start inserfill...");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新时的策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start updatefill...");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁处理
编写Configuration配置类
@Configuration
public class mybatisplusConfig {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
模拟线程插队的更新操作
User user=userMapper.selectById(8); //version=2
user.setUser("kuangsheng");
// 模拟插队线程的操作
User user1=userMapper.selectById(8);
user1.setUser("kuangsheng111");
userMapper.updateById(user1); //version=3
/*
下面这句查询其实为 select* from user where version =2
(但数据库并没有version=2的数据,所以就会导致更细失败!)
因为上面的操作将version变成3了,这就是乐观锁的机制
*/
int count=userMapper.updateById(user); //如果没有乐观锁,则改端代码的结果会 覆盖 插队线程的操作
查询操作
批量查询
List<User> userList=userMapper.selectBatchIds(Arrays.asList(1,2,3));
userList.forEach(System.out::println);
多条件查询
Map<String,Object> map=new TreeMap<>();
map.put("user","李福");
List<User> userList= userMapper.selectByMap(map);
System.out.println(userList);
分页查询
1.配置拦截器组件
// 配置分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
测试
//curren:当前页 size:每页数据条数
Page<User> page=new Page<>(1,5);
userMapper.selectPage(page,null);
List<User> userList=page.getRecords();
userList.forEach(System.out::println);
}
删除操作
单个删除
int count=userMapper.deleteById(7);
if (count>0){
System.out.println("删除成功!!!");
}
批量删除
int count=userMapper.deleteBatchIds(Arrays.asList(5,6));
if (count>0){
System.out.println("批量删除成功!!!");
}
通过map删除
Map<String,Object> map=new HashMap<>();
map.put("user","liifu");
map.put("user","cyh");
int count=userMapper.deleteByMap(map);
if(count>0){
System.out.println("删除成功!!");
}
逻辑删除
1.数据库增加一个deleted字段
2.pojo类增加对应deleted字段
@TableLogic
private int deleted; // 0:未删除 1:删除
3.编写Config配置
注意:3.3.1开始不在需要这一步了
在这里插入代码片
4.配置文件(application.yml)
#配置日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#逻辑删除
global-config:
db-config:
logic-delete-value: 1 #即删除为1
logic-not-delete-value: 0 #未删除为0
测试
int count=userMapper.deleteById(4);
if (count>0){
System.out.println("删除成功!!!");
}
删除后再次查询(看能否查出该数据)
性能分析插件
平时查询sql语句时可能会遇见一些查询比较耗时的操作。而mybatis-plus提供了性能分析插件(当超过某个时间,他就会停止执行)
条件查询器Wrapper
适用于写一些执行复杂查询的sql语句
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
// 查询 age>=21 sex="man" version=1 的信息
queryWrapper.ge("age",21).eq("sex","man").eq("version",1);
List<User> userList =userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
区间查询
QueryWrapper<User> wrapper=new QueryWrapper<>();
// 区间查询
wrapper.between("age",21,23);
int count=userMapper.selectCount(wrapper);
System.out.println(count);
查询结果数(即符合条件的条数)
QueryWrapper<User> wrapper=new QueryWrapper();
wrapper.ge("age",21).eq("version",1);
int count=userMapper.selectCount(wrapper);
System.out.println("查询的结果数="+count);
模糊查询
QueryWrapper<User> wrapper=new QueryWrapper();
// 查询age中不包含 e 且 user字段中以kuang开头的名字的数据
wrapper.notLike("age","y").likeRight("user","kuang");
List<Map<String,Object>> list=userMapper.selectMaps(wrapper);
list.forEach(System.out::println);
升序查询数据
// 升序 查询所有数据
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.orderByAsc("age");
List<User> userList=userMapper.selectList(wrapper);
userList.forEach(System.out::println);
代码自动生成器
注意点
1.要在主启动类上使用@MapperScan注解扫描mapper下的包
po属性和sql字段映射处理
1.需要在java目录下新建一个UserMapper接口,该接口继承BaseMapper类。
2.在resources目录下定义一个UserMapper.xml文件,该mapper文件的内容如下:
并使用resultMap元素定义映射关系
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hjx.mapper.UserMapper">
<resultMap id="mapper_user" type="user">
<result property="id" column="id"/>
<result property="password" column="pass_word"/>
<result property="username" column="user_name"/>
</resultMap>
</mapper>
3.最后在实体类上使用 @TableName(value = “user”,resultMap = “mapper_user”)修饰类。其中resultMap = "mapper_user"对应mapper.xml文件中的resultMap ,这样就可以实现字段和属性的映射了。如果不做处理,会报错!!
常见问题
1.当字段与属性不一样时,插入数据出现以下问题:
看到没,我的数据库字段其实是user_name,但它这里直接当成usename赋值了。
解决办法:使用@TableField注解使用exist=false将其标注为不是数据库字段的名称即可。但又出现了新的问题:
插入时,我传递的是一个user对象,并对其进行了赋值, 但它找不到我要插入的值
@Test
public void addData(){
User user=new User();
user.setPassword("123");
user.setUsername("小明");
int count=mapper.insert(user);
if (count>0){
Log.info("插入成功");
}else{
Log.info("插入失败");
}
}
目前这个问题,还不知道怎么解决------2022/1/27