-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: How to correctly remove shared instances?
PostPosted: Tue May 15, 2007 7:35 am 
Newbie

Joined: Fri Mar 09, 2007 10:12 am
Posts: 6
Hi all,

I have a many-to-many mapping between InitialStateType and Position and a one-to-many mapping between ActionsType and Position. Both mappings are unidirectional. A row in Position can be shared by InitialStateType and ActionsType (both lists have a reference on the same object in Java). Everything works fine except when I try to delete an instance of InitialStateType or ActionsType. I get a constraint violation from the database.

As the same instances of Position can be shared by InitialStateType and ActionsType, I think that, if I remove e.g. an instance of InitialStateType, Hibernate try to remove Position which are not referenced by any InitialStateType anymore (that is correct) but does not look if these Position are still referenced by ActionsType.

Hibernate should remove a Position only if it is not referenced by InitialStateType AND ActionsType anymore.

I have tried different cascading type without success. Is there a way to do this with Hibernate? How to correctly handle shared instances (one element referenced by multiple lists)?

Thank you

P.S. The mapping files are generated using HyperJAXB2.


Hibernate version: 3.2.3.ga

Mapping documents:
Code:
<hibernate-mapping auto-import="false" default-cascade="all-delete-orphan" default-lazy="false">
   <class discriminator-value="[xxx.bean.InitialStateType]"
          name="xxx.bean.InitialStateType"
          table="InitialStateType">
      <id access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
          name="Hjid"
          type="org.hibernate.type.LongType">
         <generator class="native"/>
      </id>
      <discriminator type="org.hibernate.type.StringType">
         <column name="Hjtype"/>
      </discriminator>
      <list access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor"
            name="Positions"
            table="InitialStateType_Positions">
         <key>
            <column name="InitialStateType_Positions_H_0"/>
         </key>
         <list-index>
            <column name="InitialStateType_Positions_H_1"/>
         </list-index>
         <many-to-many class="xxx.bean.Position">
            <column name="Position__Positions_Hjchildid"/>
         </many-to-many>
      </list>
     ...
      <subclass discriminator-value="xxx.bean.InitialStateType"
                name="xxx.bean.impl.InitialStateTypeImpl"/>
   </class>
</hibernate-mapping>

Code:
<hibernate-mapping auto-import="false" default-cascade="all-delete-orphan" default-lazy="false">
   <class discriminator-value="[xxx.bean.ActionsType]"
          name="xxx.bean.ActionsType"
          table="ActionsType">
      <id access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
          name="Hjid"
          type="org.hibernate.type.LongType">
         <generator class="native"/>
      </id>
      <discriminator type="org.hibernate.type.StringType">
         <column name="Hjtype"/>
      </discriminator>
      <list access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor"
            name="Positions"
            table="ActionsType_Positions">
         <key>
            <column name="ActionsType_Positions_Hjid"/>
         </key>
         <list-index>
            <column name="ActionsType_Positions_Hjindex"/>
         </list-index>
         <one-to-many class="xxx.bean.Position"/>
      </list>
      ...
      <subclass discriminator-value="xxx.bean.ActionsType"
                name="xxx..impl.ActionsTypeImpl"/>
   </class>
</hibernate-mapping>

Code:
<hibernate-mapping auto-import="false" default-cascade="all-delete-orphan" default-lazy="false">
   <class discriminator-value="[xxx.bean.Position]"
          name="xxx.bean.Position"
          table="Position_">
      <id access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
          name="Hjid"
          type="org.hibernate.type.LongType">
         <generator class="native"/>
      </id>
      <discriminator type="org.hibernate.type.StringType">
         <column name="Hjtype"/>
      </discriminator>
      <property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
                name="Speed">
         <column name="Speed"/>
         <type name="org.hibernate.type.DoubleType"/>
      </property>
      <property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
                name="Longitude">
         <column name="Longitude"/>
         <type name="org.hibernate.type.DoubleType"/>
      </property>
      ...
      <subclass discriminator-value="xxx.bean.Position"
                name="xxx.bean.impl.PositionImpl"/>
   </class>
</hibernate-mapping>


Full stack trace of any exception that occurs:
Code:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
   at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
   at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
   at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2479)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2697)
   at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:74)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
        ....
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`mission/InitialStateType_Positions`, CONSTRAINT `FK6D6552B2116044` FOREIGN KEY (`Position__Positions_Hjchildid`) REFERENCES `Position_` (`Hjid`))
   at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)
   at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912)
   at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
   ... 28 more


Name and version of the database you are using: MySQL 5.0.38 / PostgreSQL 8.2.4


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 15, 2007 11:34 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Looks like you're trying cascade="all" or cascade="delete". Try cascade="all-delete-orphan" instead. I'm not sure that it'll work, seeing as there are many different collections that a given Position might be in, but it's worth a try.

Alternatively (and more appropriately, imo) you could do the cascading in business logic. Remove all Positions from the object you're deleting, delete the object, then pass the Position to a query that checks to see if the Position is used by any entity (don't return the entity/entities, a boolean or count return is fine). If it isn't, then delete the Position.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.