5

我刚刚在 Glassfish 3 上运行的简单 Java Web 应用程序中掌握了 JPA(持久性提供程序是 EclipseLink)。到目前为止,我真的很喜欢它(除了 netbeans/glassfish 交互中的错误),但有一件事我希望能够做到,但我不知道该怎么做。

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

如果我执行常规的“从文章中选择 id、title、body”查询,我会得到一个 Article 对象列表,其中 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 上使用 tsearch2 的全文搜索 - 这是一个特定于数据库的函数,所以我使用的是 NativeQuery)

您可以看到我正在获取一个计算列,称为标题。如何将标题属性添加到我的文章类,以便它被此查询填充?

到目前为止,我已经尝试将它设置为@Transient,但最终它始终为空。

4

2 回答 2

8

可能没有好的方法可以做到这一点,只能手动:

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]);

-

@Entity
@SqlResultSetMapping(
    name = "ArticleWithHeadline",
    entities = @EntityResult(entityClass = Article.class),
    columns = @ColumnResult(name = "HEADLINE"))
public class Article {
    @Transient
    private String headline;
    ...
}
于 2010-05-28T14:20:05.210 回答
2

AFAIK,JPA 不提供对计算属性的标准化支持。使用 Hibernate,可以使用公式,但 EclipseLink 没有直接等效项。James Sutherland 在Re: Virtual columns (@Formula of Hibernate)中提出了一些建议:

没有直接的等价物(请记录增强功能),但根据您想要做的事情,有多种方法可以完成相同的事情。

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

您可以使用其描述符的 DescriptorQueryManager 覆盖类的任何 CRUD 操作的 SQL。

您可以在执行该功能的数据库上定义一个视图,并将您的实体映射到视图而不是表。

您还可以使用转换器或属性获取/设置方法执行次要翻译。

另请查看在评论中使用 a 解决方案的增强请求DescriptorEventListener

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

于 2010-05-28T15:56:34.680 回答