【发布时间】:2021-04-13 16:23:56
【问题描述】:
我需要存储某些实体的某些 String 字段的规范化(即没有特殊字符等)变体。
一个例子:
@Entity
public class Car {
@Id
private Long id;
private String make;
private String model;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "CAR_ID")
private Set<NormalizedField> normalizedFields = new HashSet();
private Set<NormalizedField> createNormalizedFields(Car car) {
Set<NormalizedField> normalized = normalize(car);
this.normalizedFields.clear();
this.normalizedFields.addAll(normalized);
}
// I would use this approach, but it doesn't allow
// changes to related entities.
// @PreCreate
// public void onCreate() {
// createNormalizedFields();
// }
}
@Entity
public class NormalizedField {
@Id
private Long id;
private String fieldName;
private String normalizedValue;
}
如果在Car 实体被持久化时自动(重新)创建标准化值会很方便。有没有办法自动触发创建方法?
使用@PrePersist, @PreUpdate... 显然不是一种选择,因为它不允许更改相关实体。
项目中没有使用Spring AOP,所以我宁愿暂时避免引入它。但无论如何,这是一个选择。
应用程序很大,“手动”管理标准化值需要大量工作,因此我将其作为最后一个选项。
【问题讨论】:
-
使用自定义的
UserType或AttributeConverter即可。 -
@M.Deinum,
AttributeConverter似乎不能用于关系属性。此外,属性本身不包含转换数据,而是需要父实体的状态。自定义UserType也存在访问父状态的相同问题。 -
我的错。我应该更仔细地阅读。 prepersist 不应该正常工作吗?我看到的主要问题是您正在清除集合并再次添加所有内容,您应该在其中更新现有的集合。此外,您应该实现正确的 equals amd hashcode 以在 Set 中使用它们。
-
PrePersist 不起作用,因为它不允许更改其中的 relation 状态。仅限非关系属性。
-
有趣;想到几个问题:(1)
normalize()的本质是什么?如果它只依赖于当前实体的状态,也许规范化的值不需要被持久化。取而代之的是,在需要时即时进行规范化(并且可能将结果缓存到@Transient字段)。 (2) 如果它依赖于Car实体之外的状态,在应用程序逻辑中执行规范化不是更合适吗? (3)NormalizedField必须是一个实体吗?您能否将其建模为持久值的集合(可能适用于PrePersist)?