MyBatis-Plus(Ⅳ)常用注解

目录

一、@TableName

解决1:通过@TableName解决问题

 解决2:通过全局配置解决问题

二、@TableId

解决1:通过@TableId解决问题

@TableId的value属性

@TableId的type属性

常用的主键策略:

示例1 在实体类使用注解

示例2 使用配置文件

三、数据规模增长(含雪花算法)

 背景

数据库分表策略

 主键生成策略

雪花算法

四、@TableField 

情况1

情况2

五、@TableLogic

物理删除&逻辑删除

实现逻辑删除

Step 1:数据库中创建逻辑删除状态列

示例 SQL:

Step 2:实体类中添加逻辑删除属性

示例实体类:

Step 3:测试逻辑删除功能

示例测试代码:

SQL 语句示例

逻辑删除操作:

查询操作:


数据库信息依旧采用MyBatis-Plus详解Ⅰ(请点击这里跳转查看)里的数据信息,在此基础上进行这一节的讲解。

一、@TableName

经过以上的测试,在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在 Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表

由此得出结论,  MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决 定,且默认操作的表名和实体类型的类名一致。

如果不一致,会发生什么?现在就测试一下,将数据库中的"user"表改成"t_user",再随机运行一个测试的方法,看看会报什么错。

解决1:通过@TableName解决问题

现在我们可以通过在实体类上使用@TableName注解而不更改数据库信息来解决这个问题。

加上注解就能解决了

 解决2:通过全局配置解决问题

在开发的过程中,我们经常遇到以上的问题,即实体类所对应的表都有固定的前缀,例如t_或tbl_

此时,可以使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就 不需要在每个实体类上通过@TableName标识实体类对应的表。

在配置文件中配置如下(.yml):

mybatis-plus:
  global-config:
    db-config:
      table-prefix: t_
# 配置MyBatis-Plus操作表的默认前缀

或是在.properties文件中:

mybatis-plus.global-config.db-config.table-prefix=t_

通过配置文件,就可以免除在实体类中添加@TableName注解了,但是注意这种方式的使用前提:实体类所对应的表都有固定的前缀(并且在 MyBatis-Plus 中,table-prefix 配置只能设置一个统一的前缀,而不能同时设置多个前缀)。

二、@TableId

经过以上的测试,  MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认基于雪花算法的策略生成id。

同时问题就来了,若实体类和表中表示主键的不是id,而是其他字段,例如uid , MyBatis-Plus会自动识别uid为主键列吗?

我们实体类中的属性id改为uid,将表中的字段id也改为uid,测试添加功能。

修改一下数据库

当然,结果肯定是报错的,因为它默认去自增id项,结果发现根本没有id字段,而且实体类中只有uid,它并无法识别uid。

如果我们不想修改数据库去解决这个问题,同样可以通过修改Java后端解决。

解决1:通过@TableId解决问题

在实体类中uid属性上通过@TableId将其标识为主键,即可成功执行SQL语句,如下:

问题解决

@TableIdvalue属性

实体类中主键对应的属性为id,而表中表示主键的字段为uid,此时若只在属性id上添加注解 @TableId,则抛出异常Unknown column'id'in'field list',即MyBatis-Plus仍然会将id作为表的主键操作,而表中表示主键的是字段uid

此时需要通过@TableId注解的value属性(遇见这种数据库和实体类名称不一致时,只设置一个@TableId就不够用了),指定表中的主键字段

@TableId("uid")或@TableId(value="uid")

@TableIdtype属性

  type属性用来定义主键策略。

常用的主键策略:

描述

IdType.ASSIGN_ID

(默认)

基于雪花算法(Snowflake)生成主键值。这种策略生成的是一个 64 位的长整型(long)主键,具有全局唯一性。它与数据库的自增策略无关,即使数据库的 id 字段没有设置为自增,也可以使用这种策略。这是 MyBatis-Plus 的默认主键策略。
IdType.AUTO使用数据库的自增策略。这种策略要求数据库的 id 字段必须设置为自增。如果数据库的 id 字段没有设置为自增,使用这种策略会导致插入失败。
IdType.INPUT用户手动输入主键值。这种策略不会自动生成主键值,需要在插入数据时显式指定主键值。
IdType.NONE等同于 IdType.INPUT,由用户手动输入主键值。这种策略不会自动生成主键值,需要在插入数据时显式指定主键值。
IdType.ASSIGN_UUID基于 UUID 生成主键值。这种策略生成的是一个 32 位的字符串(去除了 - 的 UUID)。它与数据库的自增策略无关,即使数据库的 id 字段没有设置为自增,也可以使用这种策略。
示例1 在实体类使用注解

这是我现在的数据库

现在去运行它: 

再去查看数据库:

自增了一条,而并不是雪花策略
示例2 使用配置文件

首先将实体类方才的注解注释掉,再在配置文件上配置:

重新去运行测试类中的测试语句,查看数据库:

可以发现同样生效了

使用配置注解相较于在实体类上添加注解,可以覆盖所有的实体类而不用逐个编写实体类。

三、数据规模增长(含雪花算法)

讲了这么多,mybatis-plus中的默认的雪花算法究竟是什么呢?当然,雪花算法只是应对数据规模增长策略中的其中一个,所以在讲雪花算法之前,还是有必要说一说其他几类。

 背景

在项目开发中,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量。

数据库的扩展方式主要包括:业务分库、主从复制,数据库分表。

扩展方式描述
业务分库将不同业务的数据分散存储到不同的数据库服务器,提高系统扩展性和性能。
主从复制提高系统的读取性能,通过主从复制实现数据的备份和读写分离。
数据库分表将数据分散到多个表中,应对单表数据量过大导致的性能瓶颈。

数据库分表策略

分表类型描述适用场景优点缺点
垂直分表将表中某些不常用且占大量空间的列拆分到其他表中,以提高查询性能。字段使用频率差异大,某些字段占用空间大提高查询性能增加表的复杂性
水平分表将表中的行数据分散到多个表中,适用于表行数特别大的情况。单表行数过大,性能瓶颈分布更均匀,扩展性强扩充新表复杂,数据重分布
图示

 主键生成策略

策略类型描述实现方式优点缺点
主键自增使用数据库的自增策略生成主键。数据库内置功能实现简单,性能高单表限制,不适用于分布式
分段策略将主键 ID 按照一定范围分段,例如 1-999999 放到表 1 中。手动分段,动态扩充平滑扩充新表数据分布不均匀
取模策略用主键 ID 对表的数量取模来确定数据所属的表。user_id % 表数量表分布均匀扩充新表复杂,需重分布
雪花算法分布式主键生成算法,保证全局唯一性和有序性。时间戳 + 机器ID + 序列号全局唯一,有序,高效依赖时间戳,需配置节点ID

雪花算法

特性描述
长度64 位(一个 long 类型)
符号位1 位,标识正负(通常是 0,表示正数)
时间戳41 位,存储毫秒级时间戳的差值,约等于 69.73 年
机器 ID10 位,其中 5 位是数据中心 ID,5 位是机器 ID,可部署在 1024 个节点上
序列号12 位,表示每毫秒内的流水号,每个节点每毫秒可以生成 4096 个 ID
优点整体上按照时间自增排序,全局唯一,效率高
缺点依赖时间戳,节点 ID 需要配置,可能出现时间回拨问题
图示

四、@TableField 

经过以上的测试,我们可以发现,  MyBatis-Plus在执行SQL语句时,要保证实体类中的属性名和 表中的字段名一致

如果实体类中的属性名和字段名不一致的情况,会出现什么问题呢?

情况1

 若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格.

例如:实体类属性userName,表中字段user_name

此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格

情况2

若实体类中的属性和表中的字段不满足情况1

例如:实体类属性name ,表中字段username

此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名 

假设我的数据库字段名是username,但是对我的实体类属性却写了name,我不想修改,怎么办?就可以加上这么一行注解。

就像这样

五、@TableLogic

物理删除&逻辑删除

概念描述使用场景
物理删除真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据。数据不再需要,彻底删除
逻辑删除假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍能看到此条数据记录。数据需要保留,可能需要恢复

实现逻辑删除

Step 1:数据库中创建逻辑删除状态列

  • 在数据库表中添加一个逻辑删除状态列,通常命名为 is_deleteddeleted

  • 设置默认值为 0,表示数据未被删除。

示例 SQL
ALTER TABLE t_user ADD COLUMN is_deleted TINYINT DEFAULT 0;

Step 2:实体类中添加逻辑删除属性

  • 在实体类中添加逻辑删除属性,并使用 MyBatis-Plus 的 @TableLogic 注解标记该字段。

  • @TableLogic 注解会告诉 MyBatis-Plus,这个字段用于逻辑删除。

示例实体类
package com.example.mybatisplus.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@TableName("t_user")
public class User {
    private Long id;
    private String username;
    private String name;
    private Integer age;
    private String email;
    @TableLogic
    private Integer isDeleted; // 逻辑删除字段
}

Step 3:测试逻辑删除功能

  • 测试删除功能:调用删除方法时,MyBatis-Plus 会将 is_deleted 字段的值更新为 1,而不是物理删除数据。

  • 测试查询功能:默认情况下,查询操作会自动过滤掉 is_deleted1 的数据。

示例测试代码
import com.example.mybatisplus.entity.User;
import com.example.mybatisplus.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class LogicDeleteTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testLogicDelete() {
        // 插入一条测试数据
        User user = new User();
        user.setUsername("testUser");
        user.setName("Test User");
        user.setAge(25);
        user.setEmail("test@example.com");
        userMapper.insert(user);

        // 执行逻辑删除
        userMapper.deleteById(user.getId());

        // 查询被逻辑删除的数据
        User deletedUser = userMapper.selectById(user.getId());
        assert deletedUser == null; // 默认查询不会返回逻辑删除的数据

        // 查询所有数据,包括逻辑删除的数据
        List<User> allUsers = userMapper.selectList(null);
        assert allUsers.size() == 1; // 包括逻辑删除的数据
    }
}
SQL 语句示例
  • 逻辑删除操作
    UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0;
  • 查询操作
    SELECT id, username AS name, age, email, is_deleted FROM t_user WHERE is_deleted=0;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值