Java JPA-从计算列设置实体类属性?

Java JPA-从计算列设置实体类属性?,java,postgresql,jpa,eclipselink,Java,Postgresql,Jpa,Eclipselink,我刚刚开始在GlassFish3上运行的一个简单Java web应用程序中使用JPA(持久性提供者是EclipseLink)。到目前为止,我真的很喜欢它(除了netbeans/glassfish交互中的bug),但有一件事我想能够做到,我不知道该怎么做 我有一个映射到数据库表(Article)的实体类(Article)。我试图对返回计算列的数据库执行查询,但我不知道如何设置Article类的属性,以便在调用查询时由列值填充该属性 如果我做一个常规的“从文章中选择id、title、body”查询,

我刚刚开始在GlassFish3上运行的一个简单Java web应用程序中使用JPA(持久性提供者是EclipseLink)。到目前为止,我真的很喜欢它(除了netbeans/glassfish交互中的bug),但有一件事我想能够做到,我不知道该怎么做

我有一个映射到数据库表(Article)的实体类(Article)。我试图对返回计算列的数据库执行查询,但我不知道如何设置Article类的属性,以便在调用查询时由列值填充该属性

如果我做一个常规的“从文章中选择id、title、body”查询,我会得到一个文章对象的列表,并填充id、title和body属性。这个很好用

但是,如果我执行以下操作:

Query q = em.createNativeQuery("select id,title,shorttitle,datestamp,body,true as published, ts_headline(body,q,'ShortWord=0') as headline, type from articles,to_tsquery('english',?) as q where idxfti @@ q order by ts_rank(idxfti,q) desc",Article.class);
(这是在Postgres上使用Tsarch2的全文搜索-这是一个特定于db的函数,所以我使用的是NativeQuery)

你可以看到我正在获取一个计算过的列,叫做headline。如何将headline属性添加到我的文章类中,使其由该查询填充


到目前为止,我已经尝试将其设置为@Transient,但结果是它始终为null。

可能没有好的方法,只能手动执行:

Object[] r = (Object[]) em.createNativeQuery(
    "select id,title,shorttitle,datestamp,body,true as published, ts_headline(body,q,'ShortWord=0') as headline, type from articles,to_tsquery('english',?) as q where idxfti @@ q order by ts_rank(idxfti,q) desc","ArticleWithHeadline")
    .setParameter(...).getSingleResult();

Article a = (Article) r[0];
a.setHeadline((String) r[1]);
-


另外,JPA不提供对计算属性的标准化支持。在Hibernate中,可以使用一个Eclipse,但EclipseLink没有直接的等价物。James Sutherland在文章中提出了一些建议:

没有直接等价物(请 记录增强),但取决于 你想做什么,有很多方法 完成同样的事情

日食定义了一个 TransformationMapping可以映射 来自多个字段的计算值 值,或访问数据库

您可以覆盖任何CRUD的SQL 使用其 描述符的描述符QueryManager

您可以在您的计算机上定义一个视图 执行该功能的数据库 并将实体映射到视图 而不是桌子

你也可以表演小调 使用转换器或 属性获取/设置方法

还可以查看在注释中使用
DescriptorReventListener
的解决方案

所有这些当然都是非标准的JPA

@Entity
@SqlResultSetMapping(
    name = "ArticleWithHeadline",
    entities = @EntityResult(entityClass = Article.class),
    columns = @ColumnResult(name = "HEADLINE"))
public class Article {
    @Transient
    private String headline;
    ...
}