计算属性与JPA。这在我的情况下有用吗?

时间:2015-12-21 14:17:18

标签: java jpa enums

我有一个场景,我需要配置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)

的枚举

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;

我更喜欢第一个选项,因为:

  • 使用单元测试更容易进行测试
  • 在单元测试中使用实体更容易
  • 它不需要专有扩展
  • 一般来说,SQL的可移植性可能存在一些问题,尽管在这个问题中case when与SQL 92兼容,所以它不适用于此

我唯一的问题是,最简单的方法是我们通过暴露实体的客户端内部(scenariodate属性)来放弃封装。但是你总是可以使用访问者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,并在需要时使用其他回调。