MybatisPlus

MybatisPlus(用于简化Mybatis开发)


通过MybatisPlus的引入简化Dao层的代码书写

导入mybatis-plus的依赖

java 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.10.1</version>
</dependency>

使用方式:对应的Dao接口继承BaseMapper<对应的实体对象>

java 复制代码
@Mapper
public interface UserDao extends BaseMapper<User> {
}

@Mapper也可以不写

说明:Dao接口要想被容器扫描到,有两种解决方案:

  • 方案一:在Dao接口上添加@Mapper注解,并且确保Dao处在引导类所在包或其子包中

    • 该方案的缺点是需要在每一Dao接口中添加注解
  • 方案二:在引导类上添加@MapperScan注解,其属性为所要扫描的Dao所在包

    • 该方案的好处是只需要写一次,则指定包下的所有Dao接口都能被扫描到,@Mapper就可以不写。
java 复制代码
@SpringBootApplication
@MapperScan("com.example.dao")
public class Mybatisplus01Application {
    public static void main(String[] args) {
        SpringApplication.run(Mybatisplus01Application.class, args);
    }
}

使用MybatisPlus实现数据层操作

新增

java 复制代码
@Test
void testSave(){
    User user = new User();
    user.setName("张三");
    user.setPassword("123456");
    user.setAge(23);
    user.setTel("12345678910");
    userDao.insert(user);
}

删除(通过id删除,但是id有可能是long类型即需要在长整型数后面加上一个L

java 复制代码
@Test
void testDelete(){
    userDao.deleteById(1909511862680911873L);
}

修改

java 复制代码
@Test
void testUpdate(){
    User user = new User();
    user.setId(1L);
    user.setName("张三");
    user.setPassword("123456");
    user.setAge(23);
    user.setTel("12345678910");
    userDao.updateById(user);
}

查询通过id,查询全部

java 复制代码
@Test
void testGetById() {
    User user = userDao.selectById(1L);
    System.out.println(user);
}
java 复制代码
@Test
void testGetAll() {
    List<User> userList = userDao.selectList(null);
    userList.forEach(System.out::println);
}

条件查询:通过设定一个条件对象
QueryWrapper

java 复制代码
@Test
    void testGetAll() {
        System.out.println("模糊查询");
        //创建一个查询条件对象
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 查询条件:模糊查询
        userQueryWrapper.like("name","张");
        List<User> userList = userDao.selectList(userQueryWrapper);
        userList.forEach(System.out::println);
        System.out.println("======================");
        //使用lambda格式进行条件查询
        QueryWrapper<User> qw1= new QueryWrapper<>();
        // 查询条件:小于20岁
        //User::getAge表示获取User对象的age属性---》表示lambda的方法引用
        qw1.lambda().lt(User::getAge,20);
        List<User> userList1 = userDao.selectList(qw1);
        userList1.forEach(System.out::println);
        System.out.println("======================");
        QueryWrapper<User> qw2= new QueryWrapper<>();
        // 查询条件:大于20岁小于30岁
        qw2.lambda().gt(User::getAge,20).lt(User::getAge,30);
        List<User> userList2 = userDao.selectList(qw2);
        userList2.forEach(System.out::println);
        System.out.println("======================");
        QueryWrapper<User> qw3= new QueryWrapper<>();
        //查询条件:大于20岁或者小于10岁---》通过or()方法进行连接
        qw3.lambda().gt(User::getAge,20).or().lt(User::getAge,10);
        List<User> userList3 = userDao.selectList(qw3);
        userList3.forEach(System.out::println);
    }

条件查询中的null参数值查询(在条件上就做一个判断如果不为空才进行拼接 查询的条件)

处理查询条件中的 null 值

在构建查询条件时,可以通过判断条件参数是否为 null 来决定是否添加该条件。例如:

java 复制代码
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(null != uq.getAge2(), User::getAge, uq.getAge2());
lqw.gt(null != uq.getAge(), User::getAge, uq.getAge());
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);

查询投影

可以选择查询结果中包含的属性。例如:
LambdaQueryWrapper lqw = new LambdaQueryWrapper(); lqw.select(User::getId, User::getName, User::getAge); List userList = userDao.selectList(lqw); System.out.println(userList);

范围查询

java 复制代码
LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<>();
//等同于 name=="张三",password=="123456"
lqw.eq(User::getName,"张三").eq(User::getPassword,"123456");
User user = userDao.selectOne(lqw);
System.out.println(user);
System.out.println("======================");
LambdaQueryWrapper<User> lqw1=new LambdaQueryWrapper<>();
//范围查询 between---表示在20到30岁之间前面的是下限后面的是上限
lqw1.between(User::getAge,20,30);
List<User> userList = userDao.selectList(lqw1);
userList.forEach(System.out::println);

字段映射与表映射不同

问题1:数据库表字段与实际开发中的字段不同步(@TableField(value = "pwd")

问题2:实际开发中添加了数据库表中未定义的属性(@TableField(exist = false))

问题3:采用默认查询开放了更多的字段查看权限

(比如开发中不显示出密码给用户看:@TableField(select = false))

问题4:数据库表名与在实际开发中使用的表名不同(@TableName("tbl_user")

java 复制代码
@TableName("tbl_user")
public class User {
private Long id;
private String name;
@TableField(value = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false)
private Integer online;
}

Insert操作增加一条数据的ID生成策略

通过@TableId(type="ID的生成策略")

生成策略有:

AUTO():使用数据库id自增策略控制id生成

NONE():不设置id生成策略

INPUT():用户手工输入id

ASSIGN_ID():雪花算法生成id(可兼容数值型与字符串型)+---保证唯一性,不重复---+

ASSIGN_UUID():以UUID生成算法作为id生成策略

java 复制代码
@TableId(type=IdType.ASSIGN_ID)
private Long id;

多记录操作

删除多条记录

java 复制代码
@Test
void testDelete(){
//删除指定多条数据
List list = new ArrayList<>();
list.add(1402551342481838081L);
list.add(1402553134049501186L);
list.add(1402553619611430913L);
userDao.deleteBatchIds(list);
}

查询多条记录

java 复制代码
@Test 
    void testGetByIds(){ 
        //查询指定多条数据 
        List<Long> list = new ArrayList<>(); 
        list.add(1L); 
        list.add(3L); 
        list.add(4L); 
        userDao.selectBatchIds(list); 
    } 

逻辑删除(用于设置状态字段为不可用状态,实际上字段仍然在数据表中)

复制代码
物理删除:业务数据在数据库中丢失,执行的是delete操作

逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中,执行的update操作

1、修改数据表添加deleted列

字段名可以任意,内容可以自定义,比如0表示正常,1表示删除,可以在添加列的同时设置其默认值为0正常

2、实体类添加属性

java 复制代码
@Data
//@TableName("tbl_user") 可以不写是因为配置了全局配置
public class User {
@TableId(type = IdType.ASSIGN_UUID) 
private String id; 
private String name; 
@TableField(value="pwd",select=false) 
private String password; 
private Integer age; 
private String tel; 
@TableField(exist=false) 
private Integer online; 
@TableLogic(value="0",delval="1") 
//value为正常数据的值,delval为删除数据的值 
private Integer deleted; 
}

3、运行删除方法

AI检测代码解析

java 复制代码
@SpringBootTest
class Mybatisplus03DqlApplicationTests {
	@Autowired 
	private UserDao userDao; 

	@Test 
	void testDelete(){ 
    	userDao.deleteById(1L); 
	} 
}

逻辑删除走的是update操作,会将指定的字段修改成删除状态对应的值。

说明:

1、逻辑删除MP会将所有的查询都添加一个为删除的条件,也就是已经别删除的数据是不应该被查询出来的。如果还想把已经删除的数据都查询出来,就需要如下操作:

java 复制代码
@Mapper
public interface UserDao extends BaseMapper {
//查询所有数据包含已经被删除的数据
@Select("select * from tbl_user")
public List selectAll(); }

2、如果每个表都有逻辑删除,不需要再每个模型类的属性上添加@TableLogic注解,可以在配置文件中添加全局配置,如下:

mybatis-plus:

复制代码
global-config:
	db-config:
		# 逻辑删除字段名
		logic-delete-field: deleted
		# 逻辑删除字面值:未删除为0
		logic-not-delete-value: 0
		# 逻辑删除字面值:删除为1
		logic-delete-value: 1

逻辑删除的本质是:修改操作,如果加了逻辑删除字段,查询数据时也会自动带上逻辑删除字段。

就是说在设定了相关逻辑删除字段了之后,mybatisplus执行的delete为update操作

执行的SQL语句为:
UPDATE tbl_user SET deleted=1 where id = ? AND deleted=0


相关推荐
jackson凌1 分钟前
【Java学习笔记】运算符
java·笔记·学习
咸鱼求放生14 分钟前
网络请求只到前端页面接口报200并到不到后端接口
java
只会AI搜索得coder21 分钟前
sqlite3 sqlcipher加密,解密,集成springboot,读取sqlcipher加密工具
java·spring boot·sqlite
cg50171 小时前
Spring Boot 中的自动配置原理
java·前端·数据库
纪元A梦1 小时前
华为OD机试真题——跳格子3(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
IT乐手1 小时前
Java 实现回调监听工具类
java
IT瘾君2 小时前
Java基础:Stream流操作
java
码里看花‌2 小时前
Reactor Core 中的 Flux:响应式数据流的核心实践
java
CopyLower2 小时前
Java 性能优化:从原理到实践的全面指南
java·开发语言·性能优化
ゞ 正在缓冲99%…3 小时前
leetcode14.最长公共前缀
java·算法·leetcode