JPA - Задать свойство класса сущности из вычисляемого столбца? - PullRequest
5 голосов
/ 28 мая 2010

Я только начинаю понимать JPA в простом веб-приложении на Java, работающем на Glassfish 3 (поставщик постоянства - EclipseLink). Пока что мне действительно это нравится (кроме ошибок в взаимодействии с netbeans / glassfish), но я хочу кое-что сделать, но я не знаю, как это сделать.

У меня есть класс сущности (Article), который сопоставлен с таблицей базы данных (article). Я пытаюсь выполнить запрос к базе данных, который возвращает вычисляемый столбец, но я не могу понять, как настроить свойство класса Article, чтобы свойство заполнялось значением столбца при вызове запроса.

Если я выполняю обычный запрос «выбрать идентификатор, заголовок, тело из статьи», я получаю список объектов 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);

(это полнотекстовый поиск с использованием tsearch2 на Postgres - это специфичная для БД функция, поэтому я использую NativeQuery)

Вы видите, что я выбираю вычисляемый столбец, называемый заголовком. Как добавить свойство заголовка в мой класс Article, чтобы оно заполнялось этим запросом?

До сих пор я пытался установить для него значение @Transient, но это просто приводит к тому, что оно все время равно нулю.

Ответы [ 2 ]

8 голосов
/ 28 мая 2010

Вероятно, нет хороших способов сделать это, только вручную:

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;
    ...
}
2 голосов
/ 28 мая 2010

AFAIK, JPA не предлагает стандартизированной поддержки для вычисляемых атрибутов. В Hibernate можно использовать Formula , но EclipseLink не имеет прямого эквивалента. Джеймс Сазерленд сделал несколько предложений в Re: Виртуальные столбцы (@Formula of Hibernate) хотя:

Прямого эквивалента нет (пожалуйста, войти улучшение), но в зависимости от что вы хотите сделать, есть способы выполнить то же самое.

EclipseLink определяет TransformationMapping, который может отображать вычисленное значение из нескольких полей значения или получить доступ к базе данных.

Вы можете переопределить SQL для любого CRUD операция для класса, использующего его DescriptorQueryManager дескриптора.

Вы можете определить ВИД на вашем база данных, которая выполняет функцию и сопоставьте вашу сущность с представлением вместо таблицы.

Вы также можете выполнять незначительные переводы с использованием конвертеров или методы get / set свойства.

Также взгляните на запрос на улучшение , в котором есть решение с использованием DescriptorEventListener в комментариях.

Все это, конечно, не JPA.

...