During some test for optimization we encountered a particular behavior.
We try to select in join fetch a map/list association (many-to-many) without catch the parent object but only the needed data. For sure it's not a best practice, and we do a different choice. Anyway we found that flushing the session and committing the transaction hibernate performs a delete from the association table.
Is it possible that hibernate acts as the sample hql query and some data can be involuntary lost?
We suspect this due to some user notification.
The following code and mapping is a simple situation to show the case.
Hibernate version: 2.1.5
Mapping documents:
Code:
<class lazy="true"
name="it.objectway.rp.provvigioni.be.impl.hibernate.prodotti.ProdottoGenericoImpl"
table="PRODOTTO_GENERICO"
proxy="it.objectway.rp.provvigioni.be.prodotti.ProdottoGenerico"
>
<cache usage="read-write"/>
<id name="id" type="long" column="ID">
<generator class="sequence">
<param name="sequence">PROD_GEN_SEQUENCE</param>
</generator>
</id>
<map name="codiciProdotto" table="MAPPA_COD_PRODOTTO" lazy="true"
cascade="none">
<key column="ID_PRODOTTO" />
<index-many-to-many
column="ID_TIPO_CODICE_PRODOTTO"
class="it.objectway.rp.provvigioni.be.impl.hibernate.prodotti.TipoCodiceProdottoImpl"/>
<element type="string" column="CODICE" not-null="true"/>
</map>
<property name="codice" type="string">
<column name="CODICE_RP" unique-key="pgu" />
</property>
<property name="descrizione" column="DESCRIZIONE" type="string" />
<property name="dataInizio" column="DATA_INIZIO" type="timestamp" />
<property name="dataFine" column="DATA_FINE" type="timestamp" />
</class>
<class name="it.objectway.rp.provvigioni.be.impl.hibernate.prodotti.TipoCodiceProdottoImpl"
table="TIPO_COD_PRODOTTO">
<id name="id" type="long" column="ID">
<generator class="sequence">
<param name="sequence">HIB_OBJ_SEQUENCE</param>
</generator>
</id>
<property name="codice" column="CODICE" type="string" length="15"/>
<property name="descrizione" column="DESCR" type="string" length="80"/>
</class>
Code between sessionFactory.openSession() and session.close():
Code:
//beging transaction
String query = "select cp, p.id from ProdottoGenericoImpl p join fetch p.codiciProdotto cp";
Session session = HibernateUtil.getSession();
List l = session.find(query);
//commit transaction
Name and version of the database you are using: Oracle 9i enterprise edition
The generated SQL (show_sql=true):
Code:
Hibernate: select codiciprod1_.ID_PRODOTTO as ID_PRODO1___, codiciprod1_.CODICE as CODICE__, codiciprod1_.ID_TIPO_CODICE_PRODOTTO as ID_TIPO_3___, codiciprod1_.CODICE as x0_0_, prodottoge0_.ID as x1_0_ from PRODOTTO_GENERICO prodottoge0_, MAPPA_COD_PRODOTTO codiciprod1_ where prodottoge0_.ID=codiciprod1_.ID_PRODOTTO
Hibernate: select tipocodice0_.ID as ID0_, tipocodice0_.CODICE as CODICE0_, tipocodice0_.DESCR as DESCR0_ from TIPO_COD_PRODOTTO tipocodice0_ where tipocodice0_.ID=?
Hibernate: delete from MAPPA_COD_PRODOTTO where ID_PRODOTTO=?
Hibernate: delete from MAPPA_COD_PRODOTTO where ID_PRODOTTO=?