Wie ein Criteria Objekt mit Hibernate wieder zu verwenden?
-
21-08-2019 - |
Frage
Ich versuche, Abfrageergebnis Paginierung mit Hibernate und displaytag zu tun, und Hibernate DetachedCriteria
Objekte ihr Bestes im Weg zu stehen tun. Lassen Sie mich erklären ...
Der einfachste Weg, Paginierung mit displaytag zu tun scheint die PaginatedList
Schnittstelle zu implementieren, unter anderem hat die folgenden Methoden:
/* Gets the total number of results. */
int getFullListSize();
/* Gets the current page of results. */
List getList();
/* Gets the page size. */
int getObjectsPerPage();
/* Gets the current page number. */
int getPageNumber();
/* Get the sorting column and direction */
String getSortCriterion();
SortOrderEnum getSortDirection();
Ich denke, meine PaginatedList Implementierung eines Criteria Objekt zu werfen und lassen Sie es entlang ond Linien arbeiten ...
getFullListSize() {
criteria.setProjection(Projections.rowCount());
return ((Long) criteria.uniqueResult()).intValue();
}
getList() {
if (getSortDirection() == SortOrderEnum.ASCENDING) {
criteria.addOrder(Order.asc(getSortCriterion());
} else if (getSortDirection() == SortOrderEnum.DECENDING) {
criteria.addOrder(Order.desc(getSortCriterion());
}
return criteria.list((getPageNumber() - 1) * getObjectsPerPage(),
getObjectsPerPage());
}
Aber das funktioniert nicht, weil der addOrder()
oder die setProjection()
Anrufe ändern die Kriterien, Objekt-Rendering es in verwendbar für die aufeinanderfolgenden Anrufe. Ich bin nicht ganz sicher, ob die Reihenfolge der Anrufe, aber die db wirft einen Fehler auf getFullListSize()
versucht, ein „select count(*) ... order by ...
“ zu tun, was offensichtlich falsch ist.
Ich glaube, ich könnte dieses Problem beheben, indem ein Objekt meiner eigenen Schaffung Spur von Abfragebedingungen zu halten und für jeden Anruf die Kriterien Objekt Wiederaufbau, aber das fühlt sich an wie ein weiteres Rad neu zu erfinden. Gibt es eine intelligentere Art und Weise, die möglicherweise das Kopieren die Kriterien zunächst übergeben und die Arbeit an dieser Kopie?
Update :
Es sieht aus wie getList
zuerst genannt wird, und getFullListSize
wird mehrmals nach, so, sobald es eine Bestellung übergeben, getFullListSize
fehl genannt. Es wäre sinnvoll, die db zu treffen nur einmal (in getList
würde ich sagen) und die Ergebnisse zwischenzuspeichern, ohne die Notwendigkeit zu kopieren / Zurücksetzen des Criteria
Objekt, aber immer noch ...
Update (wieder) :
Vergessen Sie, dass, sobald ich den count
getan habe ich nicht den select
tun kann, und umgekehrt. Ich brauche wirklich zwei verschiedene Criteria
Objekte.
Lösung
gut, DetachedCriteria sind Serializable, so Sie haben eingebaute (wenn unelegant) tief Klon-Unterstützung. Sie könnten die ersten Kriterien zu einem byte [] einmal auf dem Bau serialisiert, es dann Deserialisieren jedes Mal, wenn Sie wollen, es zu benutzen.
Andere Tipps
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);
Wird „Reset“ die Kriterien effektiv zwischen der rowCount Projektion und Ausführung der Kriterien selbst.
Ich würde sicherstellen, dass Ihre Bestellung vor dem rowCount tut nicht hinzugefügt wurde, wird es Dinge verlangsamen. Meine Implementierung von PaginatedList läuft immer eine Zählung Abfrage, bevor sie für Ergebnisse suchen, so Ordnung ist kein Thema.
In diesem Beitrag habe ich eine CriteriaTransformer.clone Methode entdeckt.
Das sollte die Kriterien Objekt kopieren.
Sie können auch die Projektion auf Ihrem getlist Verfahren eingestellt.
Woops Ich habe nicht bemerkt, Sie Java Hibernate bezogen sich. Wie auch immer, diese http://forum.hibernate.org/viewtopic.php?t=939039
Forenbeitrag sollte in der Lage sein, Ihre Frage zu beantworten.
hässlich es auch sein mag ich am Ende mit der Serialisierung Trick. Ich serialisiert nur das DetachedCriteria
Objekt zu einem Byte-Array auf dem Bau des PaginatedList
Objekts und de-serialisiert es bei Bedarf. Ouch.
Eine andere Sache, einen Versuch wert:
implementieren eine generische DAO wie das auf Hibernate Website vorgeschlagen und gibt es an den PaginatedList Objekt, zusammen mit einem Objekt Einschränkungen. Das PaginatedList Objekt würde dann so etwas wie
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.addOrder(<someOrder>)
und
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.setProjection(Projections.rowCount());
Haben Sie nicht versucht, dass noch nicht, aber es sollte funktionieren.
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
var dummy = criteria.ToByteArray();
return dummy.FromByteArray<DetachedCriteria>();
}