MyBatisPlus——CRUD(三)

目录:

1、MyBatisPlus——入门(一)
2、MyBatisPlus——准备(二)
3、MyBatisPlus——CRUD(三)
4、MyBatisPlus——条件查询构造器(四)


一、insert

1、插入操作

@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void insertTest() {
        User user = new User();
        user.setAge(18);
        user.setEmail("55317332@qq.com");
        user.setName("Helen");
        int result = userMapper.insert(user);
        System.out.println("添加信息为 " + user);
        System.out.println("影响行数为 " + result);
    }
    
}

注意:数据库插入id值默认为:全局唯一id
在这里插入图片描述

2、主键策略

上一步操作中,new出来的对象并没有设置主键,但是插入进去之后是18位的id

原因是:MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID

自增策略
  • 想要主键自增需要配置如下主键策略

    • 需要在创建数据表的时候设置主键自增
    • 实体字段中配置 @TableId(type = IdType.AUTO)
      在这里插入图片描述

因为创建表的时候没有设置主键自增,所以采用MyBatis-Plus的方式设置自增

  • 如果只影响一个实体类则在实体类属性上写如下注解:
@TableId(type = IdType.AUTO)
private Long id;
  • 如果想影响所有的实体配置,则在配置文件中写如下配置:
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
MyBatis-Plus所有的主键策略
  • @TableId(type = IdType.AUTO) 数据库id自增
  • @TableId(type = IdType.NONE) 未设置主键类型
  • @TableId(type = IdType.INPUT) 用户输入(需要自己的策略时使用此注解type)
  • @TableId(type = IdType.ID_WORKER) 全局唯一id(数字类型)
  • @TableId(type = IdType.ID_UUID) 全局唯一id(UUID)
  • @TableId(type = IdType.ID_WORKER_STR) 全局唯一id(字符串类型)

二、update

1、根据Id更新操作

注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

    @Test
    public void updateUserById() {
        User user = new User();
        user.setId(1L);
        user.setName("小毛");
        int result = userMapper.updateById(user);
        System.out.println("影响行数为 " + result);
    }

2、自动填充

项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作:

(1)数据库表中添加自动填充字段

在User表中添加datetime类型的新的字段 create_time、update_time

(2)实体上添加注解
    @TableField(fill = FieldFill.INSERT)   //执行添加的时候填充数据
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)   //执行更新操作的时候填充数据
    private Date updateTime;
(3)实现元对象处理器接口

注意:不要忘记添加 @Component 注解

package com.zhanc.mybatistest.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        //第一个参数   填充的类的字段(不是sql表)
        //第二个参数   当前系统时间
        //第三个参数   传进来的参数
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

3、乐观锁

主要适用场景: 当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
(1)数据库中添加version字段
ALTER TABLE `user` ADD COLUMN `version` INT;

在这里插入图片描述

(2)实体类添加version字段

并添加 @Version 注解
注意此处依然使用了填充注解@TableField,请思考,为什么更新的时候不自动填充

    @Version     //表明是  乐观锁  的字段
    @TableField(fill = FieldFill.INSERT)
    private Integer version;
(3)元对象处理器接口添加version的insert默认值
    @Override
    public void insertFill(MetaObject metaObject) {
        //第一个参数   填充的类的字段(不是sql表)
        //第二个参数   当前系统时间
        //第三个参数   传进来的参数
        
        ......
        this.setFieldValByName("version", 1, metaObject);//添加时 自动填充版本号
    }

特别说明:

  • 支持的数据类型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity 中
  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
  • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
(4)在 MybatisPlusConfig 中注册 Bean

创建配置类

package com.zhanc.mybatistest.config;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration  //表明是一个配置类
@EnableTransactionManagement   //启用相关的注解
@MapperScan("com.zhanc.mybatistest.mapper") //这里写入后主启动类不用再写
public class MybatisPlusConfig {
    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
(5)测试成功

注意: 使用乐观锁必须先查询

    @Test
    public void updateUserById2Version() {
        //查询数据
        //此处id是数据库表里之前插入的数据
        User user = userMapper.selectById(1285855724705980418L);
        System.out.println(user);
        //修改数据
        user.setName("阿创好帅");
        //执行更新
        int result = userMapper.updateById(user);
        System.out.println("影响行数为 " + result);
    }
(6)测试失败
    @Test
    public void updateUserById2Version() {
        //查询数据
        //此处id是数据库表里之前插入的数据
        User user = userMapper.selectById(1285855724705980418L);
        System.out.println(user);
        //修改数据
        user.setName("阿创好帅");
        //模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了version
		user.setVersion(user.getVersion() - 1);
		//执行更新
        int result = userMapper.updateById(user);
        System.out.println("影响行数为 " + result);
    }

三、select

1、根据id查询记录

    @Test
    public void updateUserById2Version() {
        User user = userMapper.selectById(1285855724705980418L);
        System.out.println(user);
    }

2、通过多个id批量查询

完成了动态sql的foreach的功能

    @Test
    public void selectByIds() {
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        users.stream().forEach(System.out::println);
    }

3、简单的条件查询(精准查询)

通过map封装查询条件
注意: map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需要填写user_id

    @Test
    public void selectByMap() {//map查询是精确查询
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "小毛");//此处是在拼sql,以数据库表的字段为准
        map.put("age", 22);
        List<User> list = userMapper.selectByMap(map);
        list.stream().forEach(System.out::println);
    }

4、分页

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

(1)创建配置类

此时可以删除主类中的 @MapperScan 扫描注解

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
(2)测试selectPage分页

测试: 最终通过page对象获取相关数据

@Test
public void testSelectPage() {

    Page<User> page = new Page<>(1,5);//第几页,每页大小
    userMapper.selectPage(page, null);
    
    page.getRecords().forEach(System.out::println);
    System.out.println(page.getCurrent());//打印当前页
    System.out.println(page.getPages());//打印所有的页
    System.out.println(page.getSize());//打印每一页的大小
    System.out.println(page.getTotal());//打印数据总量
    System.out.println(page.hasNext());//当前页是否有下一页
    System.out.println(page.hasPrevious());//当前页是否有前一页
}

注意:此时控制台sql语句打印:SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5

(3)测试selectMapsPage分页:结果集是Map
@Test
public void testSelectMapsPage() {

    Page<User> page = new Page<>(1, 5);
    IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page, null);

    //注意:此行必须使用 mapIPage 获取记录列表,否则会有数据类型转换错误
    mapIPage.getRecords().forEach(System.out::println);
    System.out.println(page.getCurrent());
    System.out.println(page.getPages());
    System.out.println(page.getSize());
    System.out.println(page.getTotal());
    System.out.println(page.hasNext());
    System.out.println(page.hasPrevious());
}

四、delete

1、根据id删除记录

    @Test
    public void deleteById() {
        int i = userMapper.deleteById(1L);
        System.out.println("影响行数 " + i);
    }

2、批量删除

    //批量删除
    @Test
    public void deletes() {
        int i = userMapper.deleteBatchIds(Arrays.asList(1L, 2L));
        System.out.println(i);
    }

3、简单的条件查询删除

@Test
public void testDeleteByMap() {

    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "Helen");
    map.put("age", 18);

    int result = userMapper.deleteByMap(map);
    System.out.println(result);
}

4、逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
(1)数据库中添加 deleted字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean

在这里插入图片描述

(2)实体类添加deleted 字段

并加上 @TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;
(3)元对象处理器接口添加deleted的insert默认值
    @Override
    public void insertFill(MetaObject metaObject) {
        //第一个参数   填充的类的字段(不是sql表)
        //第二个参数   当前系统时间
        //第三个参数   传进来的参数
        
        ......
        this.setFieldValByName("deleted", 0, metaObject);
    }
(4)application.properties 加入配置

此为默认值,如果你的默认值和mp默认的一样,该配置可无

#被删除是1
mybatis-plus.global-config.db-config.logic-delete-value=1
#未删除是0
mybatis-plus.global-config.db-config.logic-not-delete-value=0
(5)在 MybatisPlusConfig 中注册 Bean
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
(6)测试逻辑删除
  • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
  • 测试后分析打印的sql语句,是一条update
  • 注意: 被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
    @Test
    public void deleteById() {
        int i = userMapper.deleteById(1L);
        System.out.println("影响行数 " + i);
    }

测试后分析打印的sql语句,包含 WHERE deleted=0

SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值