-->
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.  [ 14 posts ] 
Author Message
 Post subject: Delete items of many-to-many associations
PostPosted: Tue Dec 30, 2003 9:20 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
Hello,
I have read the docs,faqs and more and still can't figure it out.
I'm using Hibernate 2.1 with mySQL 4.

My object model is using many-to-many associations for holding lists of objects.
Part of my mapping files is as follows:
A RuleBO class holds a list of actions.
The list class is ActionListBO and the action class is ActionBO.
I get a new transient RuleBO instance from the client and try to update it, so I call the session.saveOrUpdate(rule) method.
The problem:
If the client adds some actions, they are persisted and saved.
If the client deletes some actions, they are only deleted from the list item table but the actual actions aren't deleted.
Implementing it myself means that I have to compare the transient instance with the persistent instance and compute the deleted items, which is quite complicted.

Any help would be appreciated.

Eyal.

Code:
/**
* A list of actions.
* @hibernate.class  table="ActionList"
*/
public class ActionListBO extends ListBO {

  /**
   * @return m_listItems
   * @hibernate.list
   *  table="ActionListItems"
   *  lazy="true"
   *  cascade="all"
   * @hibernate.collection-key
   *  column="ListId"
   * @hibernate.collection-index
   *  column="I"
   * @hibernate.collection-many-to-many
   *  column="ActionId"
   *  class="com.mercado.s2002.businessmng.objects.rules.ActionBO"
   */
  public List getList() {
    return m_listItems;
  }

  /**
   * @param m_listItems
   */
  public void setList(List list) {
    m_listItems = list;
  }

Code:
/**
*
* @hibernate.class
*  table="Action"
*  lazy="com.mercado.s2002.businessmng.objects.rules.ActionBO"
*/
public class ActionBO {
  // the object unique identifier
  private ID m_id;
  // the object persistent version
  private int m_version;

  /**
   * Ctor.
   */
  public ActionBO () {
  }

  /**
   * Get the object id
   * @return m_id
   */
  public ID getId () {
    return  m_id;
  }

  /**
   * Set the objcte id
   * @param id
   */
  public void setId (ID id) {
    m_id = id;
  }

  /**
   * @return m_version
   * @hibernate.version
   */
  public int getVersion () {
    return  m_version;
  }

  /**
   * @param version  persistent version
   */
  public void setVersion (int version) {
    m_version = version;
  }


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 30, 2003 9:22 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Have you tried cascade="all-delete-orphan"?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 30, 2003 9:33 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
XDoclet doesn't support this setting in that context. I have tried setting it in the mapping file and it doesn't work. The problem remains.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 30, 2003 12:00 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
That's expected, you asked for a many-to-many so removing the link should not and won't remove the associated object.
If you want this kind of functionality, your association seems to be a one-to-many and then use all-delete-orphan

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 7:17 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
Ok,

Do I have to use a bidirectional one-to-many association?
I doesn't seem to work for normal associations.

Eyal


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 8:35 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Should be independent.
You're having inverse="false", aren't you ?

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 8:52 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
I'm having the default inverse flag.
The Action isn't deleted. Only the row list id and index are nullified.

Eyal


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 8:54 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Show the mapping and code

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 9:02 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
Here it is:
ActionListBO
Code:
<hibernate-mapping>
    <class
        name="com.mercado.s2002.businessmng.objects.rules.ActionListBO"
        table="ActionList"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="internalId"
            column="Id"
            type="long"
            unsaved-value="0"
        >
            <generator class="com.mercado.s2002.datastore.mapping.IdGenerator">
            </generator>
        </id>

        <version
            name="version"
            type="int"
            column="version"
        />

        <list
            name="list"
            lazy="true"
            inverse="false"
            cascade="all-delete-orphan"
        >

              <key
                  column="ListId"
              />

              <index
                  column="I"
              />

              <one-to-many
                  class="com.mercado.s2002.businessmng.objects.rules.ActionBO"
              />
        </list>

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-ActionListBO.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>

ActionBO
Code:
<hibernate-mapping>
    <class
        name="com.mercado.s2002.businessmng.objects.rules.ActionBO"
        table="Action"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="internalId"
            column="Id"
            type="long"
            unsaved-value="0"
        >
            <generator class="com.mercado.s2002.datastore.mapping.IdGenerator">
            </generator>
        </id>

        <version
            name="version"
            type="int"
            column="version"
        />

        <property
            name="actionRef"
            type="java.lang.String"
            update="true"
            insert="true"
            column="actionRef"
            not-null="true"
        />

        <property
            name="priority"
            type="double"
            update="true"
            insert="true"
            column="priority"
        />

        <property
            name="actionArgType"
            type="com.mercado.s2002.businessmng.objects.rules.constants.ActionArgType$HibernateType"
            update="true"
            insert="true"
            column="actionArgType"
            not-null="true"
        />

        <property
            name="arg"
            type="java.lang.String"
            update="true"
            insert="true"
            column="arg"
        />

        <property
            name="taskInput"
            type="com.mercado.s2002.businessmng.objects.rules.TaskInputBO"
            update="true"
            insert="true"
            column="taskInput"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-ActionBO.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>

My code:
Code:
session.saveOrUpdate(rule);

The code accepts a rule from another session. The rule contains an action list. I remove one of the actions from the list and try to update the rule.

Eyal


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 9:27 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Can't see your code but there are some limitations in the orphan delete stuff. You may NOT just freely re-assign collections to a collection role with orphan delete. You should, in fact, never call setChildren() if the children collection has orphan delete.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 9:34 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
If I understand you correctly, It will work in the following scenario:
1. Fetch an entity that has a collection from the DB.
2. In another session, remove an item from the collection.
3. Update the entity.

But it wont work if I try to update an entity with a user assigned collection. Ie. I replace the entire collection with a new one which only contains the needed items.

Eyal


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 31, 2003 11:18 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
yes Hibernate must use it's own implementation of colelction and keep state in it. Replacing the collection will screw it up.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 01, 2004 3:46 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
Ok, thanks.

Do you have a suggestion on how to implement it on my part? (Assuming I have to change the collection).

Eyal


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 01, 2004 11:34 am 
Beginner
Beginner

Joined: Thu Dec 25, 2003 8:08 am
Posts: 26
I can't find a way to implement the deletion of these orphan items. I tried doing it inside the onUpdate() in the following way:
1. Get the persistent entity from the DB.
2. Compute the orphan items.
3. Delete each item.
4. Evict the entity in order to let the modified entity to update its state.
I'm getting assertion in Hibernate code complaining about missing entities.
Code:
SEVERE: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)

net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session

   at net.sf.hibernate.impl.SessionImpl.postDelete(SessionImpl.java:2282)

   at net.sf.hibernate.impl.ScheduledDeletion.execute(ScheduledDeletion.java:30)

I'm using Hibernate version 2.1.1.

Eyal


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 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.