2009-01-14 14 views
1

Suite à la structure de classe est donnée:Résolution requête JPA trouver la dernière entrée dans la liste des connectés

class Job 
{ 
    String description; 
    Collection<JobHistory> history; 
} 

class JobHistory 
{ 
    Date assignDate; 
    User jobOwner; 
} 

class JobOwner 
{ 
    String name; 
    String id; 
} 

Cette structure de classe est accessible sur le db via JPA. Dans DAO-Layer, je peux écrire des requêtes en syntaxe JPA.

Le problème: Je veux une liste avec Job et JobHistory entrées pour un propriétaire donné avec l'identifiant donné et qui est le dernier dans le Jobhistory du travail (commandé par assignDate). Cela semble assez compliqué, peut-être plus simple: donnez-moi tous les emplois et JobHistory où le propriétaire spécifié est le propriétaire actuel du travail.

Mise à jour: pour plus de clarté, je vais changer légèrement les noms des classes.

class Job 
{ 
    String description; 
    Collection<JobOwnerHistory> history; 
} 

class JobOwnerHistory 
{ 
    Date assignDate; 
    User jobOwner; 
} 

class JobOwner 
{ 
    String name; 
    String id; 
} 

Chaque Job a une histoire de ses propriétaires classés par assignDate. Le propriétaire actuel a reçu le dernier travail attribué (c'est-à-dire MAX(assignDate)). Je veux trouver pour chaque emploi l'entrée JobOwnerHistory avec MAX(assignDate) pour un utilisateur spécifique User.

+0

Vous devez afficher le mappage. –

+0

Le mappage peut être implicite à partir des "entités" barebones: Tâche 0: M JobHistory, Utilisateur 0: M Tâche. – cletus

Répondre

1

Essayez:

SELECT j, j.history FROM Job j JOIN User u WHERE u.name = :name 

Si je devais le faire en EclipseLink, je changerais légèrement:

public List<Job> getAllJobsForUser(String username) { 
    List<Job> jobs = entityManager 
    .createQuery("SELECT j FROM Job j JOIN User u WHERE u.name = :name") 
    .setParameter("name", username) 
    .setHint(QueryHints.BATCH, "j.history") 
    .queryForList(); 
} 

La différence? Dans la première version, vous renvoyez deux objets, vous devez donc les récupérer à partir d'une liste ou d'un tableau d'objets, tandis que dans la seconde, l'indicateur de requête charge uniquement tous les historiques de travail d'une relation univoque .

Je ne sais pas si Hibernate a un équivalent à ceci. Toplink Essentials ne fait pas. Mais c'est l'une de mes fonctionnalités préférées d'EclipseLink. Oh et évidemment vous pouvez (et devriez probablement) utiliser une requête nommée au lieu d'une requête adhoc comme je l'ai fait (puisque celles-ci peuvent être vérifiées pendant la construction).

+0

Je ne sais pas si je comprends votre réponse. Je veux trouver la dernière (nouvelle) entrée dans job.history (triée par assignDate) pour chaque travail. Votre solution fonctionne-t-elle de cette façon? –

2

Je trouve la réponse suivante pour la requête:

SELECT j, h FROM Job j JOIN j.history h JOIN h.jobOwner u 
WHERE u.name = :name AND 
    (SELECT MAX(h2.assignDate) FROM Job j2 JOIN j2.history h2 
    WHERE h2 member of j.history) = h.assignDate 

La partie la plus importante dans la requête est le sous-sélection avec MAX(h2.assignDate) parce que je veux faire le travail et l'entrée la plus récente dans le propriétaire historique .