MybatisPlus处理四种表与实体的映射及id自增策略分析

在最近的工作中,碰到一个比较复杂的返回结果,发现简单映射已经解决不了这个问题了,只好去求助百度,学习mybatis表与实体的映射应该怎么写,将学习笔记结合工作碰到的问题写下本文,供自身查漏补缺,同时已被不时之需

前言

CRUD多了就形成了一种思维定势——得到的数据字段是与实体类中属性一一对应的,这么一想好像也是中规中矩,按规矩办事。难道表中的字段总是与类中的属性相对应吗?

上述就是所谓的理想情况,字段与属性一 一对应

下面我们来探究第一种可能出现的问题

一.字段与属性值不同

我更改了实体类中的属性看执行一条普通的查询会报出什么样的结果

查询失败!

因此,当表的列名和模型类的属性名发生不一致,就会导致数据封装不到模型对象,这个时候就需要其中一方做出修改

这时MP的一个注解帮我们解决了这个问题,MP给我们提供了一个注解@TableField,使用该注解可以实现模型类属性名和表的列名之间的映射关系,就像这样@TableField(value = "password")

二.表中不存在的属性

当实体类中出现了一个数据库表不存在的字段,就会导致生成的sql语句中在select的时候查询了数据库不存在的字段

具体的解决方案用到的还是@TableField注解,它有一个属性叫exist,设置该字段是否在数据库表中存在,如果设置为false则不存在,生成sql语句查询的时候,就不会再查询该字段

三.表中不存在的属性

操作后可能把一些敏感数据查询到返回给前端,这个时候我们就需要限制哪些字段默认不要进行查询,按照常理,密码等隐私信息不应该被一同查询出来,我们如何做到对这些字段的隐藏呢?还是通过@TableField注解:

@TableField注解的一个属性叫select,该属性设置默认是否需要查询该字段的值,true(默认值)表示默认查询该字段,false表示默认不查询该字段

名称@TableField
类型属性注解
位置模型类属性定义上方
作用设置当前属性对应的数据库表中的字段关系

value(默认):设置数据库表字段名称

exist: 设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用

select: 设置属性是否参与查询,此属性与select()映射配置不冲突

四.类名表名不匹配

记得懒羊羊在前段时间解决了一个bug:

简而言之,就是实体类的类名和数据库里的表名没有做到一致,导致MP不能和表相映射关联。没想到学到后面竟然可以采用注解的方式解决:

MP提供的另外一个注解@TableName来设置表与实体类之间的对应关系:

这样,我就再也不用刻意的去按照表名来写实体类啦!

名称@TableName
类型类注解
位置模型类定义上方
作用设置当前类对应于数据库表关系
相关属性value(默认):设置数据库表名称

五.id自增策略

1.type=IdType.AUTO

刚使用MP时,我就写了一个增添的方法,只不过比较奇怪的是,添加的数据主键id不是依次递增的,而是一个非常奇怪的数字,就像这样:

新增成功后,主键ID是一个很长串的内容,我们更想要的是按照数据库表字段进行自增长,而且不同的表应用不同的id生成策略比如:

日志:自增(1,2,3,4,……)

订单:特殊规则(FQ77948AK3982)

外卖单:关联地区日期等信息(50 22 24765314 87 44)

我们以自增为例:@TableId注解

名称@TableId
类型属性注解
位置模型类中用于表示主键的属性定义上方
作用设置当前类中主键属性的生成策略
相关属性value(默认):设置数据库表主键名称
type:设置主键属性的生成策略,值查照IdType的枚举值

idType的枚举类中还有很多的策略:

@Getter
public enum IdType {
    /**
     * 数据库ID自增
     * <p>该类型请确保数据库设置了 ID自增 否则无效</p>
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
     */
    NONE(1),
    /**
     * 用户输入ID
     * <p>该类型可以通过自己注册自动填充插件进行填充</p>
     */
    INPUT(2),
    /* 以下2种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 分配ID (主键类型为number或string),
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
     *
     * @since 3.3.0
     */
    ASSIGN_ID(3),
    /**
     * 分配UUID (主键类型为 string)
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
     */
    ASSIGN_UUID(4);
    private final int key;
    IdType(int key) {
        this.key = key;
    }
}

接下来我们看一下另一种策略

2.type=IdType.INPUT

通过自己注册自动填充

当关闭数据库里的自动递增,使用该策略执行增添操作时:

@TableId(type = IdType.INPUT)

    @Test
    void testSave() {
        Users user = new Users();
        user.setName("暖羊羊");
        user.setPw("777");
        user.setAge(11);
        user.setTel("26262665");
        userDao.insert(user);
    }

显然无法增添该数据,生成的SQL里竟然出现了id而在方法里没有传入id,所以我们需要自己填入:

    @Test
    void testSave() {
        Users user = new Users();
        user.setId(77L);
        user.setName("暖羊羊");
        user.setPw("777");
        user.setAge(11);
        user.setTel("26262665");
        userDao.insert(user);
    }

最后也是完成了增添

NONE不设置id生成策略
INPUT用户手工输入id
ASSIGN_ID雪花算法生成id(可兼容数值型与字符串型)
ASSIGN_UUID以UUID生成算法作为id生成策略

也是查阅了一下各种策略的优缺:

  • NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂
  • AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用
  • ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢
  • ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键

3.雪花算法简介

使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳,基本上保持自增

雪花算法是 64 位 的二进制,1位是符号位,也就是最高位,始终是0,没有任何意义,因为要是唯一计算机二进制补码中就是负数,0才是正数。41位是时间戳,具体到毫秒,41位的二进制可以使用69年,因为时间理论上永恒递增,所以根据这个排序是可以的

4.统一主键策略

在以后的项目中,为了不去分别配置每个实体类的主键策略,我们可以统一设置逐渐的策略,就像这样:

mybatis-plus:
  global-config:
    db-config:
    	id-type: assign_id

这样就做到一次配置处处统一了!

到此这篇关于MybatisPlus处理四种表与实体的映射及id自增策略分析的文章就介绍到这了,更多相关Mybatis表与实体的映射内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!

本文标题为:MybatisPlus处理四种表与实体的映射及id自增策略分析

基础教程推荐