跳到主要内容

中间表

想让中间表支持逻辑删除,需要为注解org.babyfish.jimmer.sql.JoinTable指定属性,以表示该数据是正常的还是已经被删除。

  • 一旦为中间表配置了逻辑删除属性,当任何一端的实体被逻辑删除时,所有相关的中间表记录将会被逻辑删除。

  • 所有针对当前关联的JOIN操作都会被自动加上 and 软删除标志 <> 已经被删除的条件,从而营造出某些关联已经被删除的假象。

用法

逻辑删除标志属性可以是如下类型之一

  • boolean:必须非null
  • int:必须非null
  • 枚举:必须非null
  • long/Long:null或非null即可
  • UUID: 必须非null
  • 日期:必须可null
类型代码删除状态初始状态
boolean
@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED",
type = boolean.class,
value = "true"
)
)
List<Author> authors();
truefalse
@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "ACTIVE",
type = boolean.class,
value = "false"
)
)
List<Author> authors();
falsetrue
int
@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "STATE",
type = int.class,
value = "1",
initializedValue = "0"
)
)
List<Author> authors();
10
枚举
@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "STATE",
type = State.class,
value = "DELETED",
initializedValue = "INITIALIZED"
)
)
List<Author> authors();
DELETEDINITIALIZED

long

@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_MILLIS",
type = long.class
)
)
List<Author> authors();
当前时钟毫秒数0L

Nullable Long

@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_MILLIS",
type = Long.class,
nullable = true
)
)
List<Author> authors();
当前时钟毫秒数null

UUID

@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_DATA",
type = UUID.class
)
)
List<Author> authors();
随机UUID所有字节为0的UUID

Nullable UUID

@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_DATA",
type = UUID.class,
nullable = true
)
)
List<Author> authors();
随机UUIDnull

Nullable LocalDateTime

@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_TIME",
type = LocalDateTime.class,
nullable = true,
value = "now"
)
)
List<Author> authors();
当前时间null
@ManyToMany
@JoinTable(
...省略其他属性...,
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "CREATED_TIME",
type = LocalDateTime.class,
nullable = true,
value = "null"
)
)
List<Author> authors();
null当前时间

其中

  • 第一列或第二列中的 ✩ 表示当前配置方法支持下一节即将讨论的多版本数据。

    信息

    支持逻辑删除却不考虑多版本数据的问题,是一种成熟度不高的考虑,因此建议使用支持多版本的逻辑删除配置。

  • 当前时钟毫秒数,默认行为是System.currentMillis(),即是默认的org.babyfish.jimmer.sql.meta.LogicalDeletedLongGenerator的行为。

    如果对此行为不满意,可以自定义类实现LogicalDeletedValueGenerator<Long>接口,并用如下配置

    • @JoinTable.LogicalDeletedFilter(generatedType = YourGenerator.class)

    • @JoinTable.LogicalDeletedFilter(generatedRef = YourGenerator.class),这里generatorRef表示对象在IOC容器管理框架中的名称

  • 随机UUD,默认行为是UUID.randomUUID(),即是默认的org.babyfish.jimmer.sql.meta.LogicalDeletedUUIDGenerator的行为。

    如果对此行为不满意,可以自定义类实现LogicalDeletedValueGenerator<UUID>接口,并用如下配置

    • @JoinTable.LogicalDeletedFilter(generatedType = YourGenerator.class)

    • @JoinTable.LogicalDeletedFilter(generatedRef = YourGenerator.class),这里generatorRef表示对象在IOC容器管理框架中的名称

多版本数据

逻辑删除并不会导致数据被真正删除,只会导致数据被隐藏,这代表着数据出现多版本问题。

以支持多版本数据的配置

@ManyToMany
@JoinTable(
name = "BOOK_AUTHOR_MAPPING",
joinColumnName = "BOOK_ID",
inverseJoinColumnName = "AUTHOR_ID",
logicalDeletedFilter =
@JoinTable.LogicalDeletedFilter(
columnName = "DELETED_MILLIS",
type = long.class
)
)
List<Author> authors();

为例,BOOK_AUTHOR_MAPPING表有三列,全部作为主键的组成部分

alter table BOOK_AUTHOR_MAPPING
add pk_BOOK_AUTHOR_MAPPING
primary key(
BOOK_ID,
AUTHOR_ID,
DELETED_MILLIS
);

假如表格输入如下

BOOK_IDAUTHOR_IDDELETED_MILLIS
97230
97231708796420956
97231708234681901
249110
249111708722582793
249111708664484823

其中有4条关联数据被隐藏,有效数据只有两条

BOOK_IDAUTHOR_IDDELETED_MILLIS
97230
249110