02 CRUD扩展

CRUD扩展

插入操作

    @Test
    public void testInsert(){

        User user = new User();
        user.setName("芜湖");
        user.setAge(18);
        user.setEmail("151548@qq.com");

        usermapper.insert(user);//帮我们自动生成id

    }

数据库插入的id的默认值为:全局的唯—id

主键生成策略

分布式系统唯一Id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

源码解释

public enum IdType {
    AUTO(0),//数据库id自增
    NONE(1),//未设置主键
    INPUT(2),// 手动输入
    ASSIGN_ID(3),
    ASSIGN_UUID(4),
}

主键自增:AUTO 我们需要配置主键自增

  • 在实体类字段上配置@TableId(type = IdType.AUTO)
  • 数据库字段一定是自增

手动输入:INPUT 就需要自己写id

  • 在实体类字段上配置@TableId(type = IdType.INPUT)

  • Twitter的snowflake算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心(北京、香港···),5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。

  • 具体实现的代码可以参看https://github.com/twitter/snowflake。

更新操作

    @Test
    public void testUpdate(){
        User user = new User();
        //通过条件自动拼接动态sql
        user.setId(5l);
        user.setName("啊哈");

        //注意方法名:updateById  但是参数是一个 对象!
        usermapper.updateById(user);
    }

所有的sql都是帮你自动配置的

自动填充

创建时间、更改时间! 这些操作一般都是自动化完成,我们不希望手动更新

阿里巴巴开发手册︰几乎所有的表都要配置 gmt_create、gmt_modified !而且需要自动化

方式一:数据库级别(工作中不允许修改数据库级别)

1、在表中增加字段:create_time,update_time

2、再次测试插入或更新方法,我们需要在实体类中同步!

方式二:代码级别

1、数据库字段的没有默认值

2、User类 实体类字段属性上需要增加注解

    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

3、编写处理器来处理这个注解即可!

@Slf4j
@Component //一定要把处理器加到 IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {

    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        //    default <T, E extends T> MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, E fieldVal) {
        this.strictInsertFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
        this.strictInsertFill(metaObject,"updateTime", LocalDateTime.class,LocalDateTime.now());


    }

    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictInsertFill(metaObject,"updateTime", LocalDateTime.class,LocalDateTime.now());

    }
}

4、测试插入/更新,观察时间

乐观锁&悲观锁

在面试过程中经常被问到乐观锁/悲观锁,这个其实很简单

乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不上锁!如果出现了问题,再次更新值测试

悲观锁:顾名思义十分悲观,他总是认为出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解 乐观锁机制!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
乐观锁:先查询,获得版本号
-- A
update user set name = "wsk",version = version+1 
where id = 1 and version = 1
-- B  (B线程抢先完成,此时version=2,会导致A线程修改失败!)
update user set name = "wsk",version = version+1 
where id = 1 and version = 1

测试一下Mybatis-Plus乐观锁插件

1、给数据库中增加version字段

2、实体类加对应的字段

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

3、注册组件

//扫描我们的mapper 文件夹
@MapperScan("com.kuang.mapper")
@EnableTransactionManagement
public class MyBatisPlusConfig {

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

4、测试一下

  • 成功
@Test//测试乐观锁成功
public void testOptimisticLocker1(){
	//1、查询用户信息    
	User user = userMapper.selectById(1L);
    //2、修改用户信息  
    user.setAge(18);    
    user.setEmail("2803708553@qq.com");
    //3、执行更新操作    
    userMapper.updateById(user);
	}
  • 失败
@Test//测试乐观锁失败  多线程下
public void testOptimisticLocker2(){
    //线程1
    User user1 = userMapper.selectById(1L);
    user1.setAge(1);
    user1.setEmail("2803708553@qq.com");
    //模拟另外一个线程执行了插队操作
    User user2 = userMapper.selectById(1L);
    user2.setAge(2);
    user2.setEmail("2803708553@qq.com");
    userMapper.updateById(user2);
    //自旋锁来多次尝试提交!
    userMapper.updateById(user1);//如果没有乐观锁就会覆盖插队线程的值
}

查询操作

  • 通过id查询单个用户
@Test//通过id查询单个用户
public void testSelectById(){
    User user = userMapper.selectById(1L);
    System.out.println(user);
}
  • 通过id查询多个用户
@Test//通过id查询多个用户
public void testSelectBatchIds(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
    users.forEach(System.out::println);
    //System.out.println(users);
}
  • 条件查询 通过map封装
@Test//通过条件查询之一  map
public void testMap(){
    HashMap<String, Object> map = new HashMap<>();
    //自定义要查询的
    map.put("name","www");
    map.put("age",18);
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

分页查询

分页在网站的使用十分之多!

1、原始的limit分页

2、pageHelper第三方插件

3、MybatisPlus其实也内置了分页插件!

如何使用:

1、配置拦截器组件

 //分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

2、直接使用page对象即可

@Test//测试分页查询
public void testPage(){
    //参数一current:当前页   参数二size:页面大小
    //使用了分页插件之后,所有的分页操作都变得简单了
    Page<User> page = new Page<>(2,5);
    userMapper.selectPage(page,null);
    page.getRecords().forEach(System.out::println);
    System.out.println("总页数==>"+page.getTotal());
}

删除操作

基本的删除操作:

@Test//通过id删除
public void testDeleteById(){
    userMapper.deleteById(1447818839571083267L);
}
@Test//通过id批量删除
public void testDeleteBatchIds(){
  userMapper.deleteBatchIds(Arrays.asList(1359507762519068675L,1359507762519068676L));
}

//通过map删除
@Test
public void testD(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("age","18");
    map.put("name","哈哈哈");
    userMapper.deleteByMap(map);
}

逻辑删除

步骤1: 配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig

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

步骤2: 实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

4、测试一下删除

发现: 记录还在,deleted变为1

再次测试查询被删除的用户,发现查询为空

posted @   flypiggg  阅读(29)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示