Supprimer la requête Hibernate
Lorsque j'essaie de supprimer une entrée à partir d'une base, à l'aide de
session.delete(object)
alors je peux le suivant:
1) Si la ligne est présente dans la bd puis deux requêtes SQL sont l'obtention d'exécution: Une de sélectionner et de supprimer
2) Si la ligne n'est pas présente dans la base de données, puis seulement la requête select est arriver exécuté
Mais encore une fois ce n'est pas le cas pour la mise à jour. Indépendamment de la présence de DB lignes, seule la requête de mise à jour est prise en exécution.
S'il vous plaît laissez-moi savoir pourquoi ce genre de comportement pour l'opération de suppression. N'est-il pas un problème de performance depuis deux requêtes se faire frapper plutôt qu'un seul?
Edit:
Je suis de l'utilisation d'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
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">XXX</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>
<property name="hibernate.jdbc.batch_size">30</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="hibernate.connection.pool_size">0</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.infy.model.Student" table="STUDENT">
<id name="id" column="ID">
<generator class="assigned"></generator>
</id>
<property name="firstName" type="string" column="FIRSTNAME"></property>
<property name="lastName" type="string" column="LASTNAME"></property>
<property name="city" type="string" column="CITY"></property>
<property name="state" type="string" column="STATE"></property>
<property name="country" type="string" column="COUNTRY"></property>
</class>
- Hibernate n'parfois faire un select avant une mise à Jour. Il dépend de l'état de l'objet est (persistante, transitoire ou détaché). Pour répondre à votre question, il sera utile de voir votre exemple de code.
Vous devez vous connecter pour publier un commentaire.
La raison en est que la suppression d'un objet, Hibernate exige que l'objet est dans l'état persistant. Ainsi, Hibernate premier extrait de l'objet (SÉLECTIONNER) et les supprimer (DELETE).
Pourquoi Hibernate a besoin de récupérer l'objet en premier? La raison en est que Hibernate intercepteurs peuvent être activés (http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html), et l'objet doit être transmis par le biais de ces intercepteurs pour compléter son cycle de vie. Si des lignes sont supprimer directement dans la base de données, l'intercepteur ne fonctionne pas.
D'autre part, il est possible de supprimer des entités en une seule SQL DELETE à l'aide des opérations en bloc:
assigned
ànative
alors pourquoi le supprimer pas l'exécution de la requête select avant la suppression de la ligne? c'est à dire uniquement supprimer la requête est exécutée sans l'accord préalable de sélectionner. Pourquoi comme ça?assigned
ànative
. Je n'ai pas de sauvegarder avant de le supprimer.Pour comprendre ce curieux comportement de mise en veille prolongée, il est important de comprendre quelques hibernate concepts -
Hibernate États D'Objet
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html#objectstate-overview
Opération Write-Behind
La prochaine chose à comprendre, c'est 'Opération d'Écriture derrière". Lorsque des objets attachés à une session hibernate sont modifiés, ils ne sont pas immédiatement propagées à la base de données. Hibernate ne ce pour au moins deux raisons différentes.
http://learningviacode.blogspot.com/2012/02/write-behind-technique-in-hibernate.html
Premier Niveau De Cache
Hibernate a quelque chose appelé " Premier Niveau de Cache. Chaque fois que vous passez un objet à
save()
,update()
ousaveOrUpdate()
, et chaque fois que vous récupérez un objet à l'aideload()
,get()
,list()
,iterate()
ouscroll()
, cet objet est ajouté à l'intérieur de la cache de la Session. C'est là où il suit les modifications apportées à divers objets.Hibernate Intercepters et l'Objet du Cycle de vie des Auditeurs -
De l'Intercepteur de l'interface et l'auditeur des rappels à partir de la session à la demande, autoriser l'application à vérifier et/ou de manipuler les propriétés d'un objet persistant avant de l'enregistrer, mises à jour, supprimées ou chargé.
http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/listeners.html#d0e3069
Cette section à Jour
En cascade
Hibernate permet aux applications de définir cascade de relations entre les associations. Par exemple,
'cascade-delete'
du parent à l'enfant d'association va entraîner la suppression de tous les enfants quand un parent est supprimé.Alors, pourquoi sont-ils importants.
Pour être en mesure de faire des transactions d'écriture, pour être en mesure de suivre les multiples modifications apportées aux objets (objets graphiques) et d'être en mesure d'exécuter le cycle de vie des rappels hibernate a besoin de savoir si l'objet est
transient/detached
et il a besoin d'avoir l'objet en première mémoire cache de niveau avant de faire toute modification de l'objet sous-jacent et associé des relations.C'est pourquoi hibernate (parfois) questions un
'SELECT'
déclaration de charger l'objet (si c'est pas déjà chargé) à un premier niveau de cache avant de faire des modifications.Pourquoi ne hibernate "SÉLECTIONNEZ" déclaration seulement parfois?
Hibernate questions un
'SELECT'
instruction afin de déterminer quel est l'état de l'objet est dans. Si l'instruction select retourne un objet, l'objet est dansdetached
état et si elle ne renvoie pas à un objet, l'objet est danstransient
état.À venir de votre scénario -
Supprimer - Le "Supprimer" a publié une instruction SELECT, parce que hibernate a besoin de savoir si l'objet existe dans la base de données ou non. Si l'objet existe dans la base de données, hibernate considère comme
detached
et puis re-attches à la session et le processus de suppression de cycle de vie.Mise à jour - Puisque vous êtes en appelant explicitement
'Update'
au lieu de'SaveOrUpdate'
, hibernate aveuglément suppose que l'objet est dansdetached
état, ré-attache de l'objet donné à la session de premier niveau de cache et les processus de la mise à jour de cycle de vie. Si il s'avère que l'objet n'existe pas dans la base de données contrairement à hibernate de l'assomption, une exception est levée lors de la session de bouffées de chaleur.SaveOrUpdate - Si vous appelez
'SaveOrUpdate'
, hibernate a à déterminer l'état de l'objet, de sorte qu'il utilise une instruction SELECT pour déterminer si l'objet est dansTransient/Detached
état. Si l'objet est danstransient
état, il traite le'insert'
cycle de vie et si l'objet est dansdetached
état, il traite le'Update'
cycle de vie.generator = assigned
, puis deux requêtes sont l'obtention d'exécution: sélectionnez suivie par la supprimer, mais si je change le générateur denative
alors seulement la suppression est prise en exécution. Ainsi en est-il, l'objet n'est pas en état détaché lorsque le générateur estnative
même si je attribuer l'Id?delete
àupdate
alors qu'une requête est de se faire licencier. Alors pourquoi est-ce comme le update
est dans un état persistant alors quedelete
est en état détaché?assigned
dès maintenantassigned
ànative
alors seulement le supprimer est exécuté sans aucun requête select. Pourquoi ce comportement différent pour le natif alors?Je ne suis pas sûr mais:
Si vous appelez la méthode delete avec un non transitoire de l'objet, cela signifie d'abord récupéré l'objet de la DB. Il est donc normal de voir une instruction select. Peut-être en fin de compte vous voir 2 sélectionnez + 1 supprimer?
Si vous appelez la méthode delete avec un transitoire de l'objet, alors il est possible que vous avez un
cascade="delete"
ou quelque chose de semblable, ce qui nécessite de récupérer d'abord l'objet, de sorte que "imbriqués" actions peut être effectuée que si elle est nécessaire.Edit:
L'appel à delete() avec une instance éphémère signifie faire quelque chose comme ça:
Cela permettra de supprimer la ligne avec l'id 1234, même si l'objet est un simple pojo pas récupérées par Hibernate, n'est pas présent dans son cache de session, ne sont pas gérés par Hibernate.
Si vous avez une entité association Hibernate probablement récupérer la totalité de l'entité afin qu'il sait si la suppression doit être mis en cascade pour les entités associées.
au lieu d'utiliser
utilisation
Dans les deux lieu pour
select
requête et également pourdelete
utilisationgetHibernateTemplate()
Dans
select
requête, vous devez utiliserDetachedCriteria
ouCriteria
Exemple pour la requête select
En veille prolongée éviter l'utilisation de la session,ici, je ne suis pas sûr mais le problème se produit juste à cause de l'utilisation
getHibernateTemplate()
méthode? Pouvez-vous s'il vous plaît poster le pot de nom pour la même?