web-dev-qa-db-fra.com

Différence entre CrudRepository findOne () et JpaRepository getOne ()

J'ai lu que getOne() est chargé paresseux et findOne() récupère immédiatement toute l'entité. J'ai vérifié le journal de débogage et j'ai même activé la surveillance sur mon serveur SQL pour voir quelles instructions étaient exécutées. J'ai constaté que getOne() et findOne() généraient et exécutaient la même requête. Cependant, lorsque j'utilise getOne(), les valeurs sont initialement nulles (sauf pour l'id bien sûr). 

Quelqu'un pourrait-il donc me dire si les deux méthodes exécutent la même requête sur la base de données, pourquoi devrais-je en utiliser une sur l'autre? Je cherche fondamentalement un moyen de récupérer une entité sans obtenir tous ses enfants/attributs.

EDIT1:

Code de l'entité

Code Dao: 

@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}

Journal de débogage findOne () vs getOne ()

EDIT2:

Grâce à Chlebik, j'ai pu identifier le problème. Comme Chlebik l'a déclaré, si vous essayez d'accéder à une propriété de l'entité extraite par getOne(), la requête complète sera exécutée. Dans mon cas, je vérifiais le comportement lors du débogage, en déplaçant une ligne à la fois. J'avais totalement oublié que lors du débogage, le IDE essayait d'accéder aux propriétés des objets à des fins de débogage (ou du moins c'est ce que je pense le débogage déclenche alors l’exécution complète de la requête. J'ai arrêté le débogage, puis vérifié les journaux et tout semble être normal.

getOne() vs findOne() (Ce journal est tiré de MySQL general_log et non en veille prolongée.

Journal de débogage

Pas de journal de débogage

6
prettyvoid

C'est une supposition, mais dans 'JPA pur', il existe une méthode de EntityManager appelée getReference . Et il est conçu pour récupérer une entité avec uniquement un identifiant. Son utilisation était principalement destinée à indiquer qu'il existait une référence sans qu'il soit nécessaire de récupérer l'entité entière. Peut-être que le code en dira plus:

// em is EntityManager
Department dept = em.getReference(Department.class, 30);  // Gets only     entity with ID property, rest is null
Employee emp = new Employee();
emp.setId(53);
emp.setName("Peter");
emp.setDepartment(dept);
dept.getEmployees().add(emp);
em.persist(emp);

Je suppose alors que getOne a le même objectif. Pourquoi les requêtes générées sont les mêmes que vous demandez? Eh bien, AFAIR dans JPA bible - Pro JPA2 de Mike Keith et Merrick Schincariol - presque chaque paragraphe contient quelque chose comme «le comportement dépend du fournisseur». 

MODIFIER:

J'ai défini ma propre configuration. Enfin, je suis parvenu à la conclusion que si vous interfiez de quelque manière que ce soit avec l'entité extraite avec getOne (même pour entity.getId ()), l'exécution de SQL est effectuée. Bien que si vous l'utilisez uniquement pour créer un proxy (par exemple, pour un indicateur de relation comme indiqué dans un code ci-dessus), rien ne se produit et aucun code SQL supplémentaire n'est exécuté. Donc, je suppose que dans votre classe de service, vous faites quelque chose avec cette entité (utilisez getter, enregistrez quelque chose) et c'est pourquoi le résultat de ces deux méthodes est identique.

ChlebikGitHub avec exemple de code
SO question utile n ° 1
SO question utile n ° 2

9
Chlebik

Supposons que vous souhaitiez supprimer une Entity par id. Dans SQL, vous pouvez exécuter une requête comme celle-ci:

"delete form TABLE_NAME where id = ?". 

Et dans Hibernate, vous devez d’abord obtenir une instance gérée de votre Entity, puis la transmettre à la méthode EntityManager.remove.

Entity a = em.find(Entity.class, id);
em.remove(a);

Mais de cette façon, vous devez extraire la Entity que vous souhaitez supprimer de la base de données avant la suppression. Est-ce vraiment nécessaire ?

La méthode EntityManager.getReference renvoie un proxy Hibernate sans interroger la base de données et définir les propriétés de votre entité. Sauf si vous essayez d’obtenir vous-même les propriétés du proxy renvoyé.

La méthode JpaRepository.getOne utilise la méthode EntityManager.getReference au lieu de la méthode EntityManager.find. ainsi, chaque fois que vous avez besoin d'un objet géré mais que vous n'avez pas vraiment besoin d'interroger la base de données pour cela, il est préférable d'utiliser la méthode JpaRepostory.getOne pour éliminer la requête inutile.

2
yubar45

Veuillez noter que si vous interrogez une entité par identifiant qui existe dans une base de données, avec findOne(id), vous obtenez null et avec getOne(id), vous obtenez un objet avec des champs nuls. La vérification de getOne(id) == null ne fonctionnera donc pas comme prévu.

0
Justas

Si aucune donnée n'est trouvée dans la table pour l'ID particulier, findOne renverra null, alors que getOne lancera javax.persistence.EntityNotFoundException. Les deux ont leurs propres avantages et inconvénients. Veuillez voir l'exemple ci-dessous: 

  1. Si les données non trouvées ne constituent pas un cas d'échec pour vous (par exemple. Vous ne faites que Vérifier si les données sont supprimées et que la réussite sera de Null), vous pouvez utiliser findOne.
  2. Dans un autre cas, vous pouvez utiliser getOne.

Cela peut être mis à jour selon vos besoins, si vous connaissez les résultats.

0
Kailas Andhale