Die Lösung JPA Query den letzten Eintrag in verbundener Liste zu finden,
Frage
Nach der Klassenstruktur gegeben:
class Job
{
String description;
Collection<JobHistory> history;
}
class JobHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
Diese Klasse-Struktur ist auf der db über JPA zugänglich. In der DAO-Schicht kann ich Abfragen in JPA Syntax schreiben.
Das Problem: Ich möchte eine Liste mit Job
und JobHistory
Einträgen für einen bestimmten Besitzer mit angegebener ID und wer ist die letzte in der Jobhistory
des Auftrags (geordnet nach assignDate). Klingt ziemlich kompliziert, vielleicht einfacher. Gib mir alle Aufträge und JobHistory
wo angegebenen Besitzer der tatsächliche Besitzer des Auftrags ist
Update:. für Klarheit werde ich leicht die Namen der Klassen ändern
class Job
{
String description;
Collection<JobOwnerHistory> history;
}
class JobOwnerHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
Jeder Job
hat eine Geschichte von seinen Besitzern von assignDate
sortiert. Der eigentliche Eigentümer bekam den Job zuletzt zugewiesen (das heißt MAX(assignDate)
). Ich mag für jeden Auftrag des JobOwnerHistory
Eintrag mit MAX(assignDate)
für einen bestimmten Benutzer User
finden.
Lösung
Versuchen:
SELECT j, j.history FROM Job j JOIN User u WHERE u.name = :name
Wenn ich dies in Eclipse tun, würde ich es leicht ändern:
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();
}
Der Unterschied? In der ersten Version sind Sie zwei Objekte zurückkehren, so dass Sie sie aus einer Liste abrufen oder Objekt-Arrays während in den zweiten, der Abfrage-Hinweis lädt einfach alle Auftragsprotokolle von einer (vermutlich) lazyy einer Eins-zu-viele-Beziehung .
Ich weiß nicht, ob Hibernate ein Äquivalent zu diesem hat. Toplink Essentials-nicht. Aber es ist eine meiner Lieblings-Features von Eclipse.
Oh, und natürlich können Sie (und wahrscheinlich sollen) eine benannte Abfrage statt einer Ad-hoc-Abfrage verwenden, wie ich getan habe (da diese während des Build überprüft werden).
Andere Tipps
Ich fand die folgende Antwort für die Abfrage:
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
Der wichtigste Teil in der Abfrage ist die subselect mit MAX(h2.assignDate)
, weil ich will den Job bekommen und den neuesten Eintrag in der Eigentümer-Geschichte.