2010-05-28 9 views
5

Je suis en train de me familiariser avec JPA dans une application Web Java simple exécutée sur Glassfish 3 (le fournisseur de persistance est EclipseLink). Jusqu'à présent, je l'aime vraiment (bugs dans l'interaction netbeans/glassfish à part) mais il y a une chose que je veux pouvoir faire que je ne suis pas sûr de savoir comment faire.JPA - Définition de la propriété de classe d'entité à partir d'une colonne calculée?

J'ai une classe d'entité (article) mappée à une table de base de données (article). J'essaie de faire une requête sur la base de données qui retourne une colonne calculée, mais je ne peux pas comprendre comment configurer une propriété de la classe Article afin que la propriété soit remplie par la valeur de la colonne lorsque j'appelle la requête. Si je fais une requête "select id, title, corps de l'article", j'obtiens une liste d'objets article très bien, avec les propriétés id, title et body remplies. Cela fonctionne bien.

Cependant, si je fais le ci-dessous:

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

(ceci est une recherche textuelle en utilisant tsearch2 sur Postgres - c'est une fonction spécifique db, alors j'utilise un NativeQuery)

Vous peut voir que je vais chercher une colonne calculée, appelée titre. Comment puis-je ajouter une propriété headline à ma classe Article afin qu'elle soit remplie par cette requête? Jusqu'à présent, j'ai essayé de le définir sur @Transient, mais cela finit par être null tout le temps.

Répondre

7

Il n'y a probablement pas de bonnes façons de le faire, que manuellement:

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

AFAIK, JPA ne propose pas de support standardisé pour les attributs calculés. Avec Hibernate, on utiliserait un Formula mais EclipseLink n'a pas d'équivalent direct. James Sutherland a fait quelques suggestions Re: Virtual columns (@Formula of Hibernate) si:

Il n'y a pas d'équivalent direct (s'il vous plaît un journal d'amélioration), mais en fonction de ce que que vous voulez faire, il existe des moyens de faire la même chose.

EclipseLink définit un TransformationMapping qui peut mapper une valeur calculée à partir du champ plusieurs valeurs, ou accéder à la base de données.

Vous pouvez remplacer le code SQL pour toute opération CRUD pour une classe à l'aide de son DescriptorQueryManager descripteur .

Vous pouvez définir une vue sur la base de données qui exécute la fonction et mapper votre entité à la vue au lieu de la table.

Vous pouvez également effectuer des traductions mineures à l'aide de convertisseurs ou des méthodes get/set de propriété .

ont également un regard sur le enhancement request qui a une solution en utilisant un DescriptorEventListener dans les commentaires.

Tout ceci est bien entendu une JPA non standard.

Questions connexes