当前位置: 首页 > article >正文

MybatisPlus的学习

[MyBatis-Plus] (简称 MP)是一个 [MyBatis] [ (opens new window)] 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

基于Mapper接口CRUD

Insert方法

// 插入一条记录
// T 就是要插入的实体对象
// 默认主键生成策略为雪花算法
int insert(T entity);
类型参数名描述
Tentity实体对象

 Delete方法

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 ID 删除
int deleteById(Serializable id);

// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
类型参数名描述
Wrapper<T>wrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Serializableid主键 ID
Map<String, Object>columnMap表字段 map 对象

 Update方法

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, 
            @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);

// 根据 ID 修改  主键属性必须值
int updateById(@Param(Constants.ENTITY) T entity);
类型参数名描述
Tentity实体对象 (set 条件值,可为 null)
Wrapper<T>updateWrapper实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)

Select方法 

// 根据 ID 查询
T selectById(Serializable id);

// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
类型参数名描述
Serializableid主键 ID
Wrapper<T>queryWrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Map<String, Object>columnMap表字段 map 对象
IPage<T>page分页查询条件(可以为 RowBounds.DEFAULT)

 常用的方法的代码样例

 //查询
    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        System.out.println(userList);

        List<Long> list =new ArrayList<>();
        list.add(1L);
        list.add(3L);
        List<User> users=userMapper.selectBatchIds(list);
        System.out.println("users = " + users);
    }
    //添加
    @Test
    public void testAdd() {
        User user = new User();
        user.setAge(12);
        user.setEmail("xxx");
        user.setName("大撒");
        int insert = userMapper.insert(user);
        System.out.println(insert);

    }
    //删除
    @Test
    public void testDelete() {
        int i = userMapper.deleteById("1831895769316061185");
        System.out.println("i = " + i);
        Map map=new HashMap<>();
        map.put("age",20);
        int i1 = userMapper.deleteByMap(map);
        System.out.println("i1 = " + i1);
        
    }
    //修改
    @Test
    public void testUpdate() {
        User user=new User();
        user.setId(1L);
        user.setAge(21);
        int i = userMapper.updateById(user);
        System.out.println("i = " + i);


        User user1=new User();
        user.setAge(21);
        int i1 = userMapper.update(user,null);
        System.out.println("i1 = " + i1);
    }

基于Service接口CRUD

对比Mapper接口CRUD区别:

- service添加了批量方法

- service层的方法自动添加事务

使用Iservice接口方式

接口继承IService接口

public interface UserService extends IService<User> {
}

类继承ServiceImpl实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{

}

 具体方法参考官方文档MyBatis-Plus 🚀 为简化开发而生 (baomidou.com)icon-default.png?t=O83Ahttps://baomidou.com/

MybatisPlus分页查询实现步骤

1.导入分页插件

下面这段代码放到启动类里面

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}

2.使用分页查询

@Test
public void testPageQuery(){
    //设置分页参数
    Page<User> page = new Page<>(1, 5);
    userMapper.selectPage(page, null);
    //获取分页数据
    List<User> list = page.getRecords();
    list.forEach(System.out::println);
    System.out.println("当前页:"+page.getCurrent());
    System.out.println("每页显示的条数:"+page.getSize());
    System.out.println("总记录数:"+page.getTotal());
    System.out.println("总页数:"+page.getPages());
    System.out.println("是否有上一页:"+page.hasPrevious());
    System.out.println("是否有下一页:"+page.hasNext());
}

条件构造器使用

使用MyBatis-Plus的条件构造器,你可以构建灵活、高效的查询条件,而不需要手动编写复杂的

SQL 语句。它提供了许多方法来支持各种条件操作符,并且可以通过链式调用来组合多个条件。

这样可以简化查询的编写过程,并提高开发效率。

条件构造器继承结构

Wrapper : 条件构造抽象类,最顶端父类

- AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

    - QueryWrapper : 查询/删除条件封装
    - UpdateWrapper : 修改条件封装
    - AbstractLambdaWrapper : 使用Lambda 语法
        - LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
        - LambdaUpdateWrapper : Lambda 更新封装Wrapper

 不使用QueryWrapper进行修改的原因

1.需要创建对应的实体类

2.无法将列值修改为null值!

使用queryWrapper修改

@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=?, email=? WHERE username LIKE ? AND age > ? OR email IS NULL)
    queryWrapper
            .like("username", "a")
            .gt("age", 20)
            .or()
            .isNull("email");
    User user = new User();
    user.setAge(18);
    user.setEmail("user@atguigu.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}

使用updateWrapper修改

@Test
public void testQuick2(){

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);
    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);

}

LambdaQueryWrapper对比QueryWrapper优势

QueryWrapper 示例代码:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John")
  .ge("age", 18)
  .orderByDesc("create_time")
  .last("limit 10");
List<User> userList = userMapper.selectList(queryWrapper);

LambdaQueryWrapper 示例代码:

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

lambdaQueryWrapper.eq(User::getName, "John")
  .ge(User::getAge, 18)
  .orderByDesc(User::getCreateTime)
  .last("limit 10");
List<User> userList = userMapper.selectList(lambdaQueryWrapper);

从上面的代码对比可以看出,相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属

性引用(例如 User::getName、User::getAge),而不是字符串来表示字段名,这提高了代码的可

读性和可维护性。

核心注解使用

@TableName注解

- 描述:表名注解,标识实体类对应的表

- 使用位置:实体类

@TableName("sys_user") //对应数据库表名
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

特殊情况:如果表名和实体类名相同(忽略大小写)可以省略该注解!

其他解决方案:全局设置前缀

mybatis-plus: # mybatis-plus的配置
  global-config:
    db-config:
      table-prefix: sys_ # 表名前缀字符串

@TableId 注解

- 描述:主键注解

- 使用位置:实体类主键字段

@TableName("sys_user")
public class User {
    @TableId(value="主键列名",type=主键策略)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
属性类型必须指定默认值描述
valueString""主键字段名
typeEnumIdType.NONE指定主键类型

IdType属性可选值: 

描述
AUTO数据库 ID 自增 (mysql配置主键自增长)
ASSIGN_ID(默认)分配 ID(主键类型为 Number(Long )或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)

 全局配置修改主键策略:

mybatis-plus:
  configuration:
    # 配置MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 配置MyBatis-Plus操作表的默认前缀
      table-prefix: t_
      # 配置MyBatis-Plus的主键策略
      id-type: auto

在以下场景下,添加`@TableId`注解是必要的:

1. 实体类的字段与数据库表的主键字段不同名:如果实体类中的字段与数据库表的主键字段不一

致,需要使用`@TableId`注解来指定实体类中表示主键的字段。

2. 主键生成策略不是默认策略:如果需要使用除了默认主键生成策略以外的策略,也需要添加

@TableId`注解,并通过`value`属性指定生成策略。

@TableField注解

描述:字段注解(非主键)

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    private String email;
}
属性类型       必须指定默认值描述
value    String    否 " "数据库字段名
exist     boolean    否 true            是否为数据库表字段

逻辑删除实现

概念:

逻辑删除,可以方便地实现对数据库记录的逻辑删除而不是物理删除。逻辑删除是指通过更改记录的状态或添加标记字段来模拟删除操作,从而保留了删除前的数据,便于后续的数据分析和恢复。

- 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据

- 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据     库中仍旧能看到此条数据记录

逻辑删除实现步骤:

1.数据库和实体类添加逻辑删除字段

2.指定逻辑删除字段和属性值

   a.单一指定

@Data
public class User {

   // @TableId
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    
    @TableLogic
    //逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1 
    private Integer deleted;
}

b.全局指定

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

逻辑删除以后,没有真正的删除语句,删除改为修改语句!

使用mybatis-plus数据使用乐观锁

1. 添加版本号更新插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

2.乐观锁字段添加@Version注解

- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

- 仅支持 `updateById(id)` 与 `update(entity, wrapper)` 方法

@Version
private Integer version;

3.正常更新使用即可

//演示乐观锁生效场景
@Test
public void testQuick7(){
    //步骤1: 先查询,在更新 获取version数据
    //同时查询两条,但是version唯一,最后更新的失败
    User user  = userMapper.selectById(5);
    User user1  = userMapper.selectById(5);

    user.setAge(20);
    user1.setAge(30);

    userMapper.updateById(user);
    //乐观锁生效,失败!
    userMapper.updateById(user1);
}


http://www.kler.cn/a/299004.html

相关文章:

  • [JAVA备忘录] Lambda 表达式简单介绍
  • 【WPS安装】WPS编译错误总结:WPS编译失败+仅编译成功ungrib等
  • 软件需求建模方法
  • 海外外卖APP开发新方向:基于同城外卖系统源码的多元化解决方案
  • 二叉搜索树Ⅲ【东北大学oj数据结构8-3】C++
  • 笔记本电脑需要一直插着电源吗?电脑一直充电的利弊介绍
  • 通过脚本监控MySQL是否正常启动
  • AI基础 L17 Logic Agents II
  • Git 的使用以及vscode 下git 的使用(一)
  • Java基础 2. Java基础语法
  • 请解释Java中的深拷贝和浅拷贝的区别。什么是Java中的代理模式?它有什么作用?
  • HTML5全面知识点
  • 重装电脑系统时硬盘被重新分区:数据恢复实战指南与深度解析
  • DApp开发入门指南:从概念到实践
  • 阿里云Elasticsearch AI搜索实践
  • minio实现大文件断点续传
  • SockJS的使用方法
  • 如何编辑pdf文件?金舟PDF编辑器解决PDF编辑、转换问题!
  • 华为 HCIP-Datacom H12-821 题库 (16)
  • Java项目: 基于SpringBoot+mybatis+maven实现的IT技术交流和分享平台(含源码+数据库+毕业论文)
  • 路径规划——D*算法
  • ubuntu内核升级后的问题修复
  • AMP网站如何适配提升SEO效果?
  • 编曲术语:编曲术语中英对照表
  • 安宝特方案 | 医疗AR眼镜,重新定义远程会诊体验
  • Unity Apple Vision Pro 开发(五):PolySpatial 2.0 导入方式