Hibernate Supprimer la requête

Lorsque j’essaie de supprimer une entrée d’une firebase database, en utilisant

session.delete(object) 

alors je peux le suivant:

1) Si la ligne est présente dans la firebase database, deux requêtes SQL sont exécutées: une sélection, puis une suppression.

2) Si la ligne n’est pas présente dans la firebase database, seule la requête sélectionnée est exécutée.

Mais là encore, ce n’est pas le cas pour la mise à jour. Indépendamment de la présence d’une ligne de firebase database, seule la requête de mise à jour est en cours d’exécution.

S’il vous plaît laissez-moi savoir pourquoi ce genre de comportement pour l’opération de suppression. N’est-ce pas un problème de performance puisque deux requêtes sont en train d’être touchées plutôt qu’une?

Modifier:

J’utilise Hibernate 3.2.5

Exemple de code:

 SessionFactory sessionFactory = new Configuration().configure("student.cfg.xml").buildSessionFactory(); Session session = sessionFactory.openSession(); Student student = new Student(); student.setFirstName("AAA"); student.setLastName("BBB"); student.setCity("CCC"); student.setState("DDD"); student.setCountry("EEE"); student.setId("FFF"); session.delete(student); session.flush(); session.close(); 

cfg.xml

 system XXX oracle.jdbc.OracleDriver jdbc:oracle:thin:@localhost:1521/orcl 30 org.hibernate.dialect.OracleDialect false false after_transaction true 0 thread true update 

hbm.xml

              

La raison en est que pour supprimer un object, Hibernate exige que cet object soit dans un état persistant. Ainsi, Hibernate récupère d’abord l’object (SELECT) puis le supprime (DELETE).

Pourquoi Hibernate doit-il récupérer l’object en premier? La raison en est que les intercepteurs Hibernate peuvent être activés ( http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html ) et que l’object doit passer par ces intercepteurs pour compléter son cycle de vie. . Si les lignes sont supprimées directement dans la firebase database, l’intercepteur ne s’exécutera pas.

D’autre part, il est possible de supprimer des entités dans une seule instruction SQL DELETE en utilisant des opérations en masse:

 Query q = session.createQuery("delete Entity where id = X"); q.executeUpdate(); 

Pour comprendre ce comportement particulier de l’hibernation, il est important de comprendre quelques concepts d’hibernation –

États d’object Hibernate

Transient – Un object est en état transitoire s’il a été instancié et n’est toujours pas associé à une session Hibernate.

Persistent – Une instance persistante a une représentation dans la firebase database et une valeur d’identifiant. Il a peut-être simplement été enregistré ou chargé, mais par définition dans le cadre d’une session.

Detached – Une instance détachée est un object persistant, mais sa session a été fermée.

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html#objectstate-overview

Transaction Write-Behind

La prochaine chose à comprendre est «écriture de transaction derrière». Lorsque des objects attachés à une session d’hibernation sont modifiés, ils ne sont pas immédiatement transmis à la firebase database. Hibernate le fait pour au moins deux raisons différentes.

  • Pour effectuer des insertions de lot et des mises à jour.
  • Ne propager que le dernier changement. Si un object est mis à jour plus d’une fois, il ne déclenche toujours qu’une seule instruction de mise à jour.

http://learningviacode.blogspot.com/2012/02/write-behind-technique-in-hibernate.html

Cache de premier niveau

Hibernate a quelque chose appelé “Cache de premier niveau”. Chaque fois que vous passez un object à save() , update() ou saveOrUpdate() , et chaque fois que vous récupérez un object en utilisant load() , get() , list() , iterate() ou scroll() , cet object est ajouté à le cache interne de la session. C’est là qu’il suit les modifications apscopes aux différents objects.

Intercepteurs Hibernate et auditeurs de cycle de vie des objects –

L’interface Interceptor et les rappels du programme d’écoute depuis la session vers l’application permettent à l’application d’inspecter et / ou de manipuler les propriétés d’un object persistant avant qu’il ne soit enregistré, mis à jour, supprimé ou chargé. http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/listeners.html#d0e3069


Cette section a été mise à jour

En cascade

Hibernate permet aux applications de définir des relations en cascade entre les associations. Par exemple, l’association 'cascade-delete' d’un parent à un enfant entraîne la suppression de tous les enfants lorsqu’un parent est supprimé.

Alors, pourquoi sont-ils importants?

Pour être capable d’effectuer des écritures différées, être capable de suivre plusieurs modifications d’objects (graphes d’object) et être capable d’exécuter des rappels de cycle de vie, hibernate a besoin de savoir si l’object est transient/detached et doit avoir l’object dans c’est le cache de premier niveau avant d’apporter des modifications à l’object sous-jacent et aux relations associées.

C’est pourquoi hibernate émet (parfois) une 'SELECT' pour charger l’object (s’il n’est pas déjà chargé) dans son cache de premier niveau avant de le modifier.

Pourquoi hibernate n’émet-il que parfois l’instruction SELECT?

Hibernate émet une 'SELECT' pour déterminer l’état dans lequel se trouve l’object. Si l’instruction select renvoie un object, l’object est à l’état detached et s’il ne renvoie pas d’object, l’object est en état transient .

Venir à votre scénario

Delete – Le composant ‘Delete’ a émis une instruction SELECT car hibernate doit savoir si l’object existe ou non dans la firebase database. Si l’object existe dans la firebase database, hibernate le considère comme detached , puis l’attache à nouveau à la session et traite le cycle de vie de la suppression.

Mise à jour – Puisque vous appelez explicitement 'Update' au lieu de 'SaveOrUpdate' , hibernate suppose à l’aveugle que l’object est en état detached , rattache l’object donné au cache de premier niveau de session et traite le cycle de vie de la mise à jour. S’il s’avère que l’object n’existe pas dans la firebase database contrairement à l’hypothèse d’Hibernate, une exception est levée lorsque la session est vidée.

SaveOrUpdate – Si vous appelez 'SaveOrUpdate' , hibernate doit déterminer l’état de l’object, il utilise donc une instruction SELECT pour déterminer si l’object est en état Transient/Detached . Si l’object est en état transient , il traite le cycle 'insert' vie 'insert' et si l’object est en état detached , il traite le cycle 'Update' vie 'Update' .

Je ne suis pas sûr mais:

  • Si vous appelez la méthode delete avec un object non transitoire, cela signifie d’abord que l’object a été extrait de la firebase database. Il est donc normal de voir une instruction select. Peut-être qu’à la fin vous voyez 2 select + 1 delete?

  • Si vous appelez la méthode delete avec un object transitoire, il est possible que vous ayez une cascade="delete" ou quelque chose de similaire qui nécessite de récupérer d’abord l’object afin que des “actions nestedes” puissent être effectuées si nécessaire.


Edit: appeler delete () avec une instance transitoire signifie faire quelque chose comme ça:

 MyEntity entity = new MyEntity(); entity.setId(1234); session.delete(entity); 

Cela supprimera la ligne portant l’ID 1234, même si l’object est un simple pojo non récupéré par Hibernate, non présent dans son cache de session, pas du tout géré par Hibernate.

Si vous avez une association d’entités, Hibernate doit probablement récupérer l’entité complète afin qu’elle sache si la suppression doit être effectuée en cascade avec les entités associées.

à la place d’utiliser

session.delete (object)

utilisation

 getHibernateTemplate().delete(object) 

Dans les deux cas pour select query et aussi pour delete utilisez getHibernateTemplate()

Dans la requête de select vous devez utiliser DetachedCriteria ou Criteria

Exemple pour la requête select

 List fooList = new ArrayList(); DetachedCriteria queryCriteria = DetachedCriteria.forClass(foo.class); queryCriteria.add(Ressortingctions.eq("Column_name",ressortingction)); fooList = getHibernateTemplate().findByCriteria(queryCriteria); 

En mode hibernate, évitez d’utiliser la session, ici je ne suis pas sûr mais le problème se produit simplement à cause de l’utilisation de la session