Blog

JPA-Implementierungsmuster: Abrufen von Entitäten

Vincent Partington

Aktualisiert Oktober 23, 2025
5 Minuten

Letzte Woche habe ich darüber gesprochen, wie man eine Entität speichert. Und sobald wir eine Entität gespeichert haben, möchten wir sie auch wieder abrufen. Verglichen mit der Verwaltung bidirektionaler Verknüpfungen oder dem Speichern von Entitäten ist das Abrufen von Entitäten eigentlich recht einfach. So einfach, dass ich bezweifelt habe, ob es überhaupt Sinn macht, diesen Blog zu schreiben ;-) . Allerdings haben wir beim Schreiben des Codes dafür ein paar schöne Muster verwendet. Und ich bin gespannt, welche Muster Sie zum Abrufen von Entitäten verwenden. Hier ist also die nächste Folge der Serie über JPA-Implementierungsmuster. Grundsätzlich gibt es zwei Möglichkeiten, eine Entität mit JPA abzurufen:

Ein Query-Objekt kann auch durch Verweis auf eine benannte Abfrage erstellt werden (mit EntityManager.createNamedQuery), oder durch Übergabe einer SQL-Abfrage (mit einer der drei Varianten von EntityManager.createNativeQuery). Und obwohl der Name etwas anderes vermuten lässt, kann eine Abfrage auch dazu verwendet werden, eine Aktualisierungs- oder Löschanweisung auszuführen. Eine benannte Abfrage scheint eine gute Möglichkeit zu sein, die Abfrage bei den Entitäten zu belassen, die sie abfragt, aber ich habe festgestellt, dass das nicht sehr gut funktioniert. Die meisten Abfragen benötigen Parameter, die mit einer der Varianten von Abfrage.setParameter. Wenn Sie die Abfrage und den Code, der diese Parameter setzt, zusammen halten, sind beide leichter zu verstehen. Deshalb halte ich sie in der DAO zusammen und scheue die Verwendung von benannten Abfragen. Eine Konvention, die ich für nützlich halte, ist die Unterscheidung zwischen dem Auffinden einer Entität und dem Abrufen einer Entität. Im ersten Fall wird null zurückgegeben, wenn eine Entität nicht gefunden werden kann, während im zweiten Fall eine Ausnahme geworfen wird. Die Verwendung der letzteren Methode, wenn Ihr Code erwartet, dass eine Entität vorhanden ist, verhindert, dass später NullPointerExceptionsauftauchen.

Eine einzelne Entität anhand der ID suchen und erhalten

Eine Implementierung dieses Musters für die JpaDao Basisklasse, die wir vor ein paar Blogs besprochen haben, kann wie folgt aussehen (ich habe die Find-Methode als Kontrast eingefügt):

public E findById(K id) {
  return entityManager.find(entityClass, id);
}
public E getById(K id) throws EntityNotFoundException {
  E entity = entityManager.find(entityClass, id);
  if (Entität == null) {
  throw new EntityNotFoundException(
  "Entität " + entityClass.getName() + " mit id " + id + " nicht gefunden");
  }
  return entity;
}

Natürlich müssen Sie diese neue Methode auch in der Dao Schnittstelle hinzufügen:

E getById(K id);

Suchen und Erhalten einer einzelnen Entität mit einer Abfrage

Eine ähnliche Unterscheidung kann gemacht werden, wenn wir eine Abfrage verwenden, um nach einer einzelnen Entität zu suchen. Die findOrderSubmittedAt-Methode unten gibt null zurück, wenn die Entität durch die Abfrage nicht gefunden werden kann. Die Methode getOrderSubmittedAt wirft eine NoResultException. Beide Methoden lösen eine NonUniqueResultException wenn mehr als ein Ergebnis zurückgegeben wird. Um die Methode getOrderSubmittedAt mit der Methode findById konsistent zu halten, könnten wir die NoResultException auf eine EntityNotFoundException. Aber da es beide ungeprüften Ausnahmen gibt, besteht kein wirklicher Bedarf. Da diese Methoden nur für das Order-Objekt gelten, sind sie Teil des JpaOrderDao:

public Order findOrderSubmittedAt(Date date) throws NonUniqueResultException {
  Abfrage q = entityManager.createQuery(
  "SELECT e FROM " + entityClass.getName() + " e WHERE date = :date_at");
  q.setParameter("date_at", date);
  versuchen {
  return (Bestellung) q.getSingleResult();
  } catch (NoResultException exc) {
  null zurückgeben;
  }
}
public Order getOrderSubmittedAt(Date date) throws NoResultException, NonUniqueResultException {
  Abfrage q = entityManager.createQuery(
  "SELECT e FROM " + entityClass.getName() + " e WHERE date = :date_at");
  q.setParameter("date_at", date);
  return (Bestellung) q.getSingleResult();
}

Hinzufügen der richtigen Methoden zum OrderDao Schnittstelle hinzuzufügen, bleibt eine Übung für den Leser ;-)

Suche nach mehreren Entitäten mit einer Abfrage

Natürlich wollen wir auch in der Lage sein, mehr als eine Entität zu finden. In diesem Fall finde ich, dass es keinen nützlichen Unterschied zwischen "getting" und " finding" gibt. Die Methode findOrdersSubmittedSince gibt einfach eine Liste der gefundenen Entitäten zurück. Diese Liste kann null, eine oder mehrere Entitäten enthalten. Sehen Sie sich den folgenden Code an:

public List findOrdersSubmittedSince(Date date) {
  Abfrage q = entityManager.createQuery(
  "SELECT e FROM " + entityClass.getName() + " e WHERE date >= :date_since");
  q.setParameter("date_since", date);
  return (Liste) q.getResultList();
}

Aufmerksame Leser werden feststellen, dass diese Methode bereits in der ersten Version von JpaOrderDao. Während das Abrufen von Entitäten also ziemlich einfach ist, gibt es ein paar Muster, an die Sie sich bei der Implementierung von Finders und Getters halten können. Natürlich würde es mich interessieren, wie Sie dies in Ihrem Code handhaben. P.S. JPA 1.0 unterstützt dies noch nicht, aber JPA 2.0 wird eine Criteria API enthalten. Die Criteria API wird es Ihnen ermöglichen, JPA-Abfragen dynamisch zu erstellen. Criteria-Abfragen sind flexibler als String-Abfragen, so dass Sie sie abhängig von der Eingabe in einem Suchformular erstellen können. Und da Sie sie mit Hilfe von Domänenobjekten definieren, sind sie einfacher zu pflegen, da Verweise auf Domänenobjekte automatisch refaktorisiert werden. Leider verlangt die Criteria-API, dass Sie die Eigenschaften Ihrer Entität mit ihrem Namen referenzieren. Ihre IDE wird Ihnen also nicht helfen, wenn Sie diese umbenennen. Eine Liste aller Blogs zu JPA-Implementierungsmustern finden Sie in der Zusammenfassung der JPA-Implementierungsmuster.

Verfasst von

Vincent Partington

Contact

Let’s discuss how we can support your journey.