我有一个由唯一标识符和版本标识的实体,并在
@Embeddable
主键中使用两者。为了识别哪个版本当前是“活动的”,还有一个具有该名称的布尔标志(规则是只有具有给定唯一标识符的一行可以设置活动标志)。
@Embeddable
class PrimaryKey {
private long uniqueIdentifier;
private int version;
// etc.
}
@Entity
class Entity {
@Id
private PrimaryKey id;
// etc.
private boolean active; // only true for at max 1 version for any given uniqueIdentifier
}
到目前为止,很简单。这与 Hibernate 配合得很好,并允许我查询任何给定版本 (
WHERE uniqueIdentifier = ? and version = ?
) 或任何当前版本 (WHERE uniqueIdentifier = ? and active = true
)。
我还得到了另一个包含我的实体的实体...
@Entity
class ParentEntity {
@OneToOne
private Entity entity;
}
显然,
ParentEntity
的表包含两列,例如 entity_uniqueIdentifier
和 entity_version
。
现在,出于业务原因,我想做的是使
entity_version
可空的
ParentEntity
列。期望的行为如下......
ParentEntity
时,entity_version
是 not null
,加载给定版本的实体ParentEntity
(其中 entity_version
为 null
)时,加载活动标志为 true 的实体。管理字段(设置它等)不是这里的问题,我唯一的问题是加载它时。有谁知道如何使用 Hibernate 来做到这一点?还可能吗?
以防万一有人绊倒这个......
我们找到了两种可能的解决方案,一种不太好,另一种稍微好一些(恕我直言):
首先,如果不是
PostLoadEntityListener
,可以使用 Hibernate 中的 Entity
来替换 active == true
。这个解决方案并不是很好,因为它对性能有影响,更重要的是,它有点“隐藏”,必须知道这个 EntityListener 已配置等。所以我们基本上放弃了该解决方案。
更好的是
ParentEntity
中的这个...
@Column(name = entity_uniqueIdentifier")
public Long entityUniueIdentifier;
@Column(name = "entity_version")
public Integer entityVersion;
@OneToOne()
@Immutable
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(column = @JoinColumn(name = "entity_uniqueIdentifier", updatable = false, insertable = false, referencedColumnName = "uniqueIdentifier")),
@JoinColumnOrFormula(formula = @JoinFormula(value = "(CASE WHEN entity_version is not null THEN entity_version ELSE (SELECT MAX(i.version) FROM Entity i WHERE i.uniqueIdentifier = entity_uniqueIdentifier AND i.active) END)", referencedColumnName = "version"))
})
public Entity entity;
通过设置版本或将其保留为空,我们可以控制
ParentEntity
是否会加载 active
Entity
或具有给定 Entity
的 version
。