我有一个场景,我需要配置2个标签。标签名称为“Out Date”和“In Date”。我在数据库中只有一个名为'Date'的字段。无论是“Out”还是“In”,都是在运行时通过Enum'Scenario'的值决定的。但是,我需要实际向用户显示Out Date& In Date,以便他可以选择其中一个或两个。我听说JPA将在这方面有所帮助。这是真的,还是有其他方法可以实现这一点。下面是一些示例代码。
日期
@Override
@Convert("DateTimeConverter")
@Column(name = "DATE")
public DateTime getDate() {
return date;
}
方案
@Override
@Convert("EnumConverter")
@Column(name = "SCENARIO")
public Scenario getScenario() {
return scenario;
}
场景是任何值为OUT(1),IN(2)
的枚举答案 0 :(得分:2)
JPA中没有计算属性。
您可以使用@Transient
注释创建非持久性但基于其他字段计算的属性:
@Transient
public DateTime getInDate() {
if (scenario == Scenario.IN) {
return date;
}
return null;
}
@Transient
public DateTime getOutDate() {
if (scenario == Scenario.OUT) {
return date;
}
return null;
}
或者,如果您使用的是Hibernate,则可以使用专有注释@Formula
:
@Formula("case when SCENARIO = 2 then DATE else NULL end")
@Convert("DateTimeConverter")
private DateTime inDate;
@Formula("case when SCENARIO = 1 then DATE else NULL end")
@Convert("DateTimeConverter")
private DateTime outDate;
我更喜欢第一个选项,因为:
case when
与SQL 92兼容,所以它不适用于此我唯一的问题是,最简单的方法是我们通过暴露实体的客户端内部(scenario
和date
属性)来放弃封装。但是你总是可以使用访问者protected
隐藏这些属性,JPA仍然可以处理它。
答案 1 :(得分:1)
要计算JPA实体中的属性,可以使用JPA回调。
请参阅此Hibernate JPA Callbacks文档。 (注意:JPA回调并非特定于hibernate,它是最新JPA 2.1 specification的一部分)。 还有这个OpenJpa JPA Calbacks一个。
以下实体生命周期类别有一个 Pre 和 Post 事件,实体管理器可以拦截这些事件来调用方法:
因此,我们假设您要在标题为实体的两个持久实体字段 label1 和 label2 中计算 complexLabel 标签 MyEntity :
uploadImage: function (formData)
{
return $http.post('js/upload.php', formData,
{
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
});
}
正如@Dawid所写,你必须使用 @Transient 注释 complexLabel ,以便通过持久性忽略它们。如果你不这样做,持久性就会失败,因为 MyEntity 对应表中没有这样的列。
使用 @PostLoad 注释,实体管理器在从持久性加载任何 MyEntity 实例后立即调用 computeComplexLabel()方法。 因此, @PostLoad 带注释的方法最适合放置您的帖子加载实体属性增强代码。
Bellow是关于 PostLoad 的JPA 2.1规范的摘录:
实体执行后,将调用实体的 PostLoad 方法 从数据库或当前加载到当前持久化上下文中 在应用了刷新操作之后。 PostLoad 在返回或访问查询结果之前调用方法或 在遍历关联之前。
修改强>
正如@Dawid指出的那样,如果你想在实体更新后立即计算这个瞬态字段,你也可以使用@PostUpdate,并在需要时使用其他回调。