it-swarm.com.de

JPA: Wie erhält man Entität basierend auf einem anderen Feldwert als ID?

Wenn in JPA (Hibernate) das ID-Feld automatisch generiert wird, wird davon ausgegangen, dass der Benutzer über diesen Schlüssel keine Kenntnis hat. Beim Abrufen der Entität würde der Benutzer also eine Abfrage durchführen, die auf einem anderen Feld als der ID basiert. Wie erhalten wir die Entität in diesem Fall (da em.find() nicht verwendet werden kann)? 

Ich verstehe, dass wir eine Abfrage verwenden und die Ergebnisse später filtern können. Aber gibt es einen direkteren Weg (weil dies ein sehr häufiges Problem ist, wie ich es verstehe).

43
Neo

Es ist kein "Problem", wie Sie es sagten.

Der Ruhezustand verfügt über die integrierte Funktion find(). Sie müssen jedoch eine eigene Abfrage erstellen, um ein bestimmtes Objekt abzurufen. Ich empfehle die Verwendung von Hibernate 's Criteria:

Criteria criteria = session.createCriteria(YourClass.class);
YourObject yourObject = criteria.add(Restrictions.eq("yourField", yourFieldValue))
                             .uniqueResult();

Dadurch wird eine criteria für Ihre aktuelle Klasse erstellt, und die Einschränkung wird hinzugefügt, dass die Spalte "yourField" dem Wert yourFieldValue entspricht. uniqueResult() weist ihn an, ein eindeutiges Ergebnis zu erzielen. Wenn mehr Objekte übereinstimmen, sollten Sie eine Liste abrufen.

List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list();

Wenn Sie weitere Fragen haben, wenden Sie sich bitte an uns. Hoffe das hilft.

30
Raul Rene

wenn Sie über ein Repository für Entität Foo verfügen und alle Einträge mit dem exakten Zeichenfolgenwert boo auswählen müssen (funktioniert auch für andere primitive Typen oder Entitätstypen) Fügen Sie dies in Ihre Repository-Schnittstelle ein:

List<Foo> findByBoo(String boo);

wenn Sie Ergebnisse bestellen müssen:

List<Foo> findByBooOrderById(String boo);

Mehr dazu unter reference .

12
cici

Grundsätzlich sollten Sie ein bestimmtes eindeutiges Feld hinzufügen. Ich verwende normalerweise xxxUri Felder.

class User {

    @Id
    // automatically generated
    private Long id;

    // globally unique id
    @Column(name = "SCN", nullable = false, unique = true)
    private String scn;
}

Und Ihre Geschäftsmethode wird dies tun.

public User findUserByScn(@NotNull final String scn) {
    CriteriaBuilder builder = manager.getCriteriaBuilder();
    CriteriaQuery<User> criteria = builder.createQuery(User.class);
    Root<User> from = criteria.from(User.class);
    criteria.select(from);
    criteria.where(builder.equal(from.get(User_.scn), scn));
    TypedQuery<User> typed = manager.createQuery(criteria);
    try {
        return typed.getSingleResult();
    } catch (final NoResultException nre) {
        return null;
    }
}
7
Jin Kwon

Die bewährte Methode ist die Verwendung der Annotation @NaturalId. Es kann als Geschäftsschlüssel verwendet werden. In manchen Fällen ist es zu kompliziert, daher werden einige Felder in der Realität als Bezeichner verwendet. Zum Beispiel habe ich eine Benutzerklasse mit einer Benutzer-ID als Primärschlüssel und E-Mail ist auch ein eindeutiges Feld. Wir können also E-Mail als natürliche ID verwenden 

@Entity
@Table(name="user")
public class User {
  @Id
  @Column(name="id")
  private int id;

  @NaturalId
  @Column(name="email")
  private String email;

  @Column(name="name")
  private String name;
}

Um unseren Rekord zu erhalten, benutzen Sie einfach 'session.byNaturalId ()'

Session session = sessionFactory.getCurrentSession();
User user = session.byNaturalId(User.class)
                   .using("email","[email protected]")
                   .load()
2

Schreiben Sie eine benutzerdefinierte Methode wie diese: 

public Object findByYourField(Class entityClass, String yourFieldValue)
{
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery(entityClass);
    Root<Object> root = criteriaQuery.from(entityClass);
    criteriaQuery.select(root);

    ParameterExpression<String> params = criteriaBuilder.parameter(String.class);
    criteriaQuery.where(criteriaBuilder.equal(root.get("yourField"), params));

    TypedQuery<Object> query = entityManager.createQuery(criteriaQuery);
    query.setParameter(params, yourFieldValue);

    List<Object> queryResult = query.getResultList();

    Object returnObject = null;

    if (CollectionUtils.isNotEmpty(queryResult)) {
        returnObject = queryResult.get(0);
    }

    return returnObject;
}
2
tinker_fairy

Ich habe eine Bibliothek geschrieben, die genau dies ermöglicht. Es ermöglicht die Suche nach Objekt, indem einfach nur die Felder initialisiert werden, nach denen Sie filtern möchten: https://github.com/kg6zvp/GenericEntityEJB

0
KG6ZVP

Schauen Sie sich an:

0
Wilhelm Kleu

In meiner Spring-Boot-App habe ich ein ähnliches Problem wie dieses gelöst:

@Autowired
private EntityManager entityManager;

public User findByEmail(String email) {
    User user = null;
    Query query = entityManager.createQuery("SELECT u FROM User u WHERE u.email=:email");
    query.setParameter("email", email);
    try {
        user = (User) query.getSingleResult();
    } catch (Exception e) {
        // Handle exception
    }
    return user;
}
0
Sareneathenodny

Siehe - Spring docs für Abfragemethoden

Wir können Methoden in Spring Jpa hinzufügen, indem wir diff-Parameter in Methoden wie den folgenden übergeben:
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

// Enabling static ORDER BY for a query 

List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
0
Chinmoy