MybatisPlus-对Mybatis的增删改查之扩展

insert插入

测试插入SQL,学习主键生成策略

一、编写插入方法的测试代码

@SpringBootTest
class MybatisplusApplicationTests {
   //将UserMapper自动装配到测试类中,因为继承了父类BaseMapper,所有的方法都来自父类
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //查询全部用户,这里需要传递一个Wrapper(条件构造器),后面讲解
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
    
    //测试插入方法
    @Test
    public void testInsert(){
        //插入方法中需要传递一个User对象
        User user = new User();
        
        //通过set方法往对象中传数据,注意这里不给id传数据
        user.setName("张三");
        user.setAge(19);
        user.setEmail("123131@qq.com");
        
        //调用BaseMapper封装的insert方法,把user对象传进去,返回一个受影响的行数
        int result = userMapper.insert(user);
        System.out.println(result); //result表示受影响的行数
        
        //再次打印刚刚创建的对象
        System.out.println(user);
    }

}

二、运行测试方法,控制台打印结果
发现我们并没有给User对象传递id的参数,系统默认给生成了一个id

三、这里就涉及到了许多的主键生成策略
先拓展一个分布式唯一id生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.html (cnblogs.com)
现在我们系统中默认是用的雪花算法
1、认识什么是雪花算法

2、系统当前默认的主键策略是雪花策略,我们还可以通过注解@TableId设置其他的策略

不同的主键生成策略

通过学习注解@TableId,我们可以了解到可以个性化修改主键的生成策略

点进IdType,发现可以有以下的选择:

一、上一小节讲过了系统当前默认的雪花算法策略,可以回顾一下

二、AUTO表示自增策略,使用方法如下
1、首先在实体类的属性上加上注解@TableId,将Type赋值了AUTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

2、在数据库中同步操作,将指定的id字段也修改为自增,不然就会报错
注意:修改完表,一定记得点击保存,不然IDEA还是会报错!!!!!!

3、在测试类中测试

@SpringBootTest
class MybatisplusApplicationTests {
   //将UserMapper自动装配到测试类中,因为继承了父类BaseMapper,所有的方法都来自父类
    @Autowired
    private UserMapper userMapper;
    
    //测试插入方法
    @Test
    public void testInsert(){
        //插入方法中需要传递一个User对象
        User user = new User();

        //通过set方法往对象中传数据,注意这里不给id传数据
        user.setName("里弗斯");
        user.setAge(13);
        user.setEmail("666631@qq.com");

        //调用BaseMapper封装的insert方法,把user对象传进去,返回一个受影响的行数
        int result = userMapper.insert(user);
        System.out.println(result); //result表示受影响的行数

        //再次打印刚刚创建的对象
        System.out.println(user);
    }
}

控制台打印结果:
原本数据库共有6条数据,测试代码中我没有给里弗斯这条数据传id,现在因为我设置了主键自增策略,所以他就自动被赋值为7

三、剩余的策略解释

update更新

通过id更新数据

一、当前数据库的数据


二、编写测试更新的代码

@SpringBootTest
class MybatisplusApplicationTests {
   //将UserMapper自动装配到测试类中,因为继承了父类BaseMapper,所有的方法都来自父类
    @Autowired
    private UserMapper userMapper;
    
    //测试更新
    @Test
    public void testUpdate(){
        //更新方法中需要传递一个User对象
        User user = new User();

        //通过set方法往对象中传数据
        user.setId(1L);
        user.setName("詹姆斯");
        user.setAge(38);
        //注意:这里的通过id更新数据,需要传进一个User对象
        userMapper.updateById(user);
    }
}

三、执行代码,控制台打印结果
MybatisPlus的强大之处是在于它可以根据我们传递进去的参数,自动生成动态SQL

四、观察数据库中数据也成功更新

自动填充

一、为什么要使用自动填充?
每一张数据表中,几乎都会有创建时间、修改时间,但是这些字段在阿里巴巴开发手册中明确规定了,比如gmt_create、gmt_modified几乎所有的表都需要配置上,而且必须实现自动化填充!!!!!!

二、实现自动填充的两种方式
1、数据库级别
(1)在表中新增gmt_create、gmt_modified字段,别忘记修改完点击保存
记得更新时间勾选上更具当前的时间戳更新数据

(2)再次执行更新数据,先在实体类中把字段同步        

 private Date gmt_create;
 private Date gmt_modified; 
    //测试更新
    @Test
    public void testUpdate(){
        //更新方法中需要传递一个User对象
        User user = new User();

        //通过set方法往对象中传数据
        user.setId(1L);
        user.setName("詹姆斯");
        user.setAge(35);
        //注意:这里的通过id更新数据,需要传进一个User对象
        userMapper.updateById(user);
    }

查询数据库更新时间列,的确根据当前更新的时间发生了改变

2、代码级别
(1)删除数据库对创建和更新使劲按字段的默认值或者自动更新操作

(2)在实体类的字段上增加注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    //使用注解@TableField,设置该字段是在什么情况下自动填充更新,默认是不更新
    @TableField(fill = FieldFill.INSERT)
    private Date gmt_create;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmt_modified;
}

(3)编写处理器来处理这些注解
原理就是我们手动创建一个处理器,并通过@Component注解将该处理器添加到Spring容器中,当我们对某个表中的指定字段做插入或者更新操作的时候,处理器就会对指定的字段填充响应的数据

@Slf4j //可以查看日志信息
@Component //将该类声明为Spring的组件,添加到IOC容器中,才能有效
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
    log.info("insertFull start.....");
    //调用setFieldValByName方法,把指定的字段填充成希望的数据
    this.setFieldValByName("gmt_create",new Date(),metaObject);
    this.setFieldValByName("gmt_modified",new Date(),metaObject);
    }
    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("updateFull start.....");
        //更新操作,只更新gmt_modified字段即可
        this.setFieldValByName("gmt_modified",new Date(),metaObject);
    }
}

(4)测试执行插入或者更新操作的代码

@SpringBootTest
class MybatisplusApplicationTests {
   //将UserMapper自动装配到测试类中,因为继承了父类BaseMapper,所有的方法都来自父类
    @Autowired
    private UserMapper userMapper;

    //测试插入方法
    @Test
    public void testInsert(){
        //插入方法中需要传递一个User对象
        User user = new User();

        //通过set方法往对象中传数据,注意这里不给id传数据
        user.setName("恩比德");
        user.setAge(66);
        user.setEmail("64534654644546@qq.com");

        //调用BaseMapper封装的insert方法,把user对象传进去,返回一个受影响的行数
        int result = userMapper.insert(user);
        System.out.println(result); //result表示受影响的行数

        //再次打印刚刚创建的对象
        System.out.println(user);
    }

    //测试更新
    @Test
    public void testUpdate(){
        //更新方法中需要传递一个User对象
        User user = new User();

        //通过set方法往对象中传数据
        user.setId(2L);
        user.setName("库里");
        user.setAge(28);
        //注意:这里的通过id更新数据,需要传进一个User对象
        userMapper.updateById(user);
    }

}

(5)观察数据库表时间的更新状态,操作成功!

乐观锁插件处理

一、推出这款插件的意图
多线程下,当更新一条记录的时候,希望这条记录没有被别人更新

二、乐观锁的实现方式
1、取出记录时,获取当前的version
2、更新时,带上这个version
3、执行更新时

update XXX set name = "张三",version = newVersion where version = oldVersion

4、如果version不对,那么就更新失败
假设有两条线程,A线程和B线程,两个线程都取出了记录,假设这个原始的version = 1,
如果线程B抢先线程A先更新了数据,version发生了改变,那么线程A再执行更新数据的时候就会发现version不对,更新失败!


三、测试使用乐观锁插件
1、首先在数据库表中增加一个version字段

2、实体类中更新字段,并且在version字段上面增加注解@Version,标记该字段加上了乐观锁

    @Version //乐观锁注解
    private Integer version;

3、注册组件
在项目下新建一个config包,下面新建一个mybatisplus的核心配置类,注意这里把扫描mybatis的Mapper接口注解从主启动类中挪到了
mybatisplus的核心配置类下,注册乐观锁的方法,死代码将来直接用

@MapperScan("com.guohui.mapper") //扫描mapper文件夹,编写的mapper接口才能生效
@Configuration //声明该类是一个配置类
public class MybatisPlusConfig {

    //注册乐观锁插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

4、测试乐观锁
(1)单线程下,测试更新数据,肯定能成功将数据更新

    //测试乐观锁一:单线程下数据可以更新成功
    @Test
    public void testOptimisticLocker(){
        //1、通过id查到某个user对象
        User user = userMapper.selectById(1l);
        //2、对这个对象进行更新操作
        user.setName("阿里巴巴");
        user.setAge(99);
        //3、执行一下更新操作,把上面的user对象传进去,此时的对象中的version是1
        userMapper.updateById(user);

    }

数据库中对应数据的version成功更新,默认是执行version+1

(2)多线程下,测试同时更新一行数据,会更新失败

    //测试乐观锁二:多线程下数据会更新失败
    @Test
    public void testOptimisticLocker01() {
        User user1 = userMapper.selectById(2l);
        user1.setName("东七七");
        user1.setAge(43);
        //此时另一个模拟线程过来插队
        User user2 = userMapper.selectById(2l);
        user2.setName("西六六");
        user2.setAge(34);
        userMapper.updateById(user2);
        userMapper.updateById(user1);
    }

(3)查看数据库的表,确实发现只更新了user2中的数据

(4)查看并分析控制台的执行日志

select查询

常规查询

    @Test
    public void testSelect(){
        //1.查询单个用户,直接把id传进去即可
        User user = userMapper.selectById(1l);
        System.out.println(user);

        //2.批量查询用户
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3, 4));
        users.forEach(System.out::println);

        //3.通过map来按照条件查询,它可以自动帮我们将map中的数据拼接成动态的SQL
        Map<String, Object> map = new HashMap<>();
        map.put("name","詹姆斯");
        List<User> userList = userMapper.selectByMap(map);
        userList.forEach(System.out::println);
    }

分页查询(插件)

分页在网站中的使用十分频繁,MybatisPlus也内置了分页的插件,所以可以直接拿来使用
一、使用方法
1、在MybatisPlusConfig核心配置文件中注册分页插件

@MapperScan("com.guohui.mapper") //扫描mapper文件夹,编写的mapper接口才能生效
@Configuration //声明该类是一个配置类
public class MybatisPlusConfig {
    
    //注册分页插件
    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor(){
        return new PaginationInnerInterceptor();
    }
}

2、测试类中,直接使用Page对象即可

    //测试分页查询
    @Test
    public void testPage(){
        Page<User> page = new Page<>(1,5); //两个参数的作用:查询第一页,显示5条数据
        userMapper.selectPage(page, null); //调用selectPage,第二个参数暂时空着
        page.getRecords().forEach(System.out::println);
    }

delete删除

常规删除

    //测试删除
    @Test
    public void testDelete(){
        //通过id删除,DELETE FROM user WHERE id = ?
        userMapper.deleteById(8l);
        
        //批量删除,DELETE FROM user WHERE id IN(?,?,?)
        userMapper.deleteBatchIds(Arrays.asList(4,5,6));
        
        //通过map自定义删除,动态拼接SQL,DELETE FROM user WHERE id = ?
        Map<String, Object> map = new HashMap<>();
        map.put("id",7);
        userMapper.deleteByMap(map);
    }

逻辑删除(插件)

一、首先先了解两个概念
1、物理删除
从数据库中直接移除
2、逻辑删除
在数据库中没有被移除,而是通过一个变量来让他失效!比如说deleted = 0变为deleted = 1

二、测试逻辑删除
1、在数据库表中增加一个deleted字段,默认值为0

2、实体类pojo中更新字段,并且增加逻辑删除的注解

@TableLogic //逻辑删除注解
private Integer deleted;

3、在application.properties中配置逻辑删除

#配置逻辑删除,删除了deleted字段为1,没有删除的为0
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

4、测试删除
(1)数据库原数据

(2)执行删除操作

    //测试逻辑删除
    @Test
    public void testDelete(){
        //通过id删除,DELETE FROM user WHERE id = ?
        userMapper.deleteById(1l);
    }

注意:我们虽然执行的是删除的方法,但是它实际执行的是更新的SQL        

(3)查看数据库更新数据
发现我们这条数据依旧存在,但是deleted的值发生了改变

更加有意思的是,我们再对第一条数据执行查询操作的时候,他会自动帮助我们把deleted = 0拼接上去,所以这条数据就无法查询到。换句话说,逻辑删除的插件会让系统自动过滤掉被逻辑删除的数据

至此,关于MybatisPlus对Mybatis的CRUD扩展的介绍就结束了,你已经掌握了对常规的增删改查的功能,后续会继续更新,欢迎交流和指正!

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MyBatis-Plus是一个基于MyBatis的增强工具,它简化了开发人员在使用MyBatis进行数据库操作时的繁琐工作。在使用MyBatis-Plus进行多表增删改查时,可以利用MyBatis-Plus提供的实体类注解、条件构造器、Wrapper等功能来简化操作。 多表增删改查的具体操作步骤如下: 1. 多表查询:使用MyBatis-Plus的Wrapper类来构建查询条件,例如: ```java Wrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("user_type", 1).like("user_name", "John"); List<User> userList = userMapper.selectList(wrapper); ``` 2. 多表插入:使用MyBatis-Plus的实体类注解来指定关联关系,例如: ```java @TableName("user") public class User { @TableField(exist = false) private List<Role> roles; // ... } @TableName("role") public class Role { // ... } ``` 然后在插入用户时,可以通过关联关系插入角色信息: ```java User user = new User(); user.setName("John"); Role role = new Role(); role.setName("admin"); user.setRoles(Collections.singletonList(role)); userMapper.insert(user); ``` 3. 多表更新:使用MyBatis-Plus的Wrapper类来构建更新条件,例如: ```java Wrapper<User> wrapper = new UpdateWrapper<>(); wrapper.eq("user_type", 1).like("user_name", "John"); User user = new User(); user.setEmail("john@example.com"); userMapper.update(user, wrapper); ``` 4. 多表删除:使用MyBatis-Plus的Wrapper类来构建删除条件,例如: ```java Wrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("user_type", 1).like("user_name", "John"); userMapper.delete(wrapper); ``` 以上就是使用MyBatis-Plus进行多表增删改查的基本操作步骤,你可以根据具体的业务需求进行相应的调整和扩展

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值