Dans JPA (Hibernate), lorsque nous générons automatiquement le champ ID, on suppose que l'utilisateur n'a aucune connaissance de cette clé. Ainsi, lorsqu’il obtient l’entité, l’utilisateur interroge sur un champ autre que l’ID. Comment pouvons-nous obtenir l'entité dans ce cas (puisque em.find()
ne peut pas être utilisé).
Je comprends que nous pouvons utiliser une requête et filtrer les résultats plus tard. Mais existe-t-il un moyen plus direct (car c’est un problème très courant, si je comprends bien).
Ce n'est pas un "problème" comme vous l'avez dit.
Hibernate a la find()
intégrée, mais vous devez créer votre propre requête pour obtenir un objet particulier. Je recommande d’utiliser Hibernate 's Criteria
:
Criteria criteria = session.createCriteria(YourClass.class);
YourObject yourObject = criteria.add(Restrictions.eq("yourField", yourFieldValue))
.uniqueResult();
Cela créera une criteria
sur votre classe actuelle, en ajoutant la restriction que la colonne "yourField" est égale à la valeur yourFieldValue
. uniqueResult()
lui dit d'apporter un résultat unique. Si plusieurs objets correspondent, vous devriez récupérer une liste.
List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list();
Si vous avez d'autres questions, n'hésitez pas à demander. J'espère que cela t'aides.
si vous avez un référentiel pour entité Foo
et devez sélectionner toutes les entrées avec la valeur de chaîne exacte boo
(fonctionne également pour d'autres types primitifs ou types d'entité). Mettez ceci dans votre interface de référentiel:
List<Foo> findByBoo(String boo);
si vous avez besoin de commander des résultats:
List<Foo> findByBooOrderById(String boo);
Voir plus à référence .
Fondamentalement, vous devez ajouter un champ unique spécifique. J'utilise habituellement des champs xxxUri
.
class User {
@Id
// automatically generated
private Long id;
// globally unique id
@Column(name = "SCN", nullable = false, unique = true)
private String scn;
}
Et votre méthode commerciale fera comme ça.
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;
}
}
La meilleure pratique consiste à utiliser l'annotation @NaturalId. Elle peut être utilisée comme clé commerciale dans certains cas. Elle est trop compliquée. Certains champs utilisent donc cet identifiant dans le monde réel. Par exemple, j'ai une classe d'utilisateurs avec l'ID utilisateur comme clé primaire et le courrier électronique est également un champ unique. Nous pouvons donc utiliser le courrier électronique comme identifiant naturel
@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;
}
Pour obtenir notre enregistrement, utilisez simplement 'session.byNaturalId ()'
Session session = sessionFactory.getCurrentSession();
User user = session.byNaturalId(User.class)
.using("email","[email protected]")
.load()
Ecrivez une méthode personnalisée comme ceci:
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;
}
J'ai écrit une bibliothèque qui aide précisément à faire cela. Il permet une recherche par objet simplement en initialisant les champs que vous souhaitez filtrer par: https://github.com/kg6zvp/GenericEntityEJB
Jettes un coup d'oeil à:
JPA query language
: Le langage de requête Java Persistence JPA Criteria API
: Utilisation de l'API Criteria pour créer des requêtesDans mon application de démarrage Spring, j'ai résolu un problème similaire à celui-ci:
@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;
}