-->
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.  [ 5 posts ] 
Author Message
 Post subject: Deleting child from parent bag problem (all-delete-orphan).
PostPosted: Fri Jul 27, 2007 6:44 am 
Newbie

Joined: Mon Jun 25, 2007 11:35 am
Posts: 15
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
Nhibernate 1.2

Mapping documents:
Tag
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping namespace="it.telecomitalia.Gecko.BusinessEntities.Domain" xmlns="urn:nhibernate-mapping-2.2">
<class name="Tag, it.telecomitalia.Gecko.BusinessEntities" table="Tags" lazy="false">
<id name="TagID" column="TagID" type="String">
<generator class="assigned" />
</id>

<bag name="Informazioni" table="Tags_Informazioni" cascade="all-delete-orphan">
<key column="TagID"/>
<many-to-many column="InformazioneID" class="Informazione, it.telecomitalia.Gecko.BusinessEntities"/>
</bag>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping namespace="it.telecomitalia.Gecko.BusinessEntities.Domain" xmlns="urn:nhibernate-mapping-2.2">
<class name="Informazione, it.telecomitalia.Gecko.BusinessEntities" table="Informazioni" lazy="false">
<id name="InformazioneID" column="InformazioneID" type="Int64">
<generator class="identity" />
</id>

<property name="Testo" column="Testo" type="string"/>
</class>
</hibernate-mapping>

Code between sessionFactory.openSession() and session.close():
[Test]
public void TestEliminaCriticitaFromTag()
{
NHibernateSessionManager.Instance.BeginTransaction();

IInformazioneDao informazioneDao = daoFactory.GetInformazioneDao();
Informazione informazione = informazioneDao.GetById(248, false);

ITagDao tagDao = daoFactory.GetTagDao();

// 1111111111111111 0000000000000000
SimpleExpression expression = Expression.Eq("TagID", "0000000000000000");
List<Tag> tags = ((TagDao) tagDao).GetByCriteria(new ICriterion[] {expression});

if (tags.Count != 0)
{
Tag tag = tags[0];
tag.Informazioni.Remove(informazione);
tagDao.SaveOrUpdate(tag);
}

NHibernateSessionManager.Instance.CommitTransaction();
}


Name and version of the database you are using:
MS SQL Server 2005


HAllo i got this problem.

I Have two Tag object with a reference to the same Informazione.

When i remove one Informazione from the tag collection tag.Informazioni.Remove(informazione); the option cascade="all-delete-orphan" deletes the informazione also from the other object (i can see it from db).

Any idea why?

Kind regards.

Massimo


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 27, 2007 7:52 am 
Beginner
Beginner

Joined: Tue Jul 10, 2007 5:27 am
Posts: 34
Location: Belgium
try changing the cascade option to "save-update"

i think the cascade option refers to the entities of the other side of the many-to-many relationship, not the actual link record. The link records are taken care of automatically, and the cascade option doesn't really affect those. At least, i think that's how it is, but i'm not entirely sure though.

_________________
Davy Brion
http://ralinx.wordpress.com


Top
 Profile  
 
 Post subject: Problem deleting child with cascade="all-delete-orphan&
PostPosted: Tue Aug 07, 2007 6:07 am 
Newbie

Joined: Mon Jun 25, 2007 11:35 am
Posts: 15
DavyBrion wrote:
try changing the cascade option to "save-update"

i think the cascade option refers to the entities of the other side of the many-to-many relationship, not the actual link record. The link records are taken care of automatically, and the cascade option doesn't really affect those. At least, i think that's how it is, but i'm not entirely sure though.


I tried to make a simple unit test to understand what is going on with my problem but it seems not to work anyway.

So i got these two mapping files:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Tag, BusinessEntities" table="Tags" lazy="false">
<id name="TagID" column="TagID" type="String">
<generator class="assigned" />
</id>
<bag name="Informazioni" table="Tags_Informazioni" cascade="all-delete-orphan">
<key column="TagID"/>
<many-to-many column="InformazioneID" class="Informazione, BusinessEntities"/>
</bag>
</class>
</hibernate-mapping>


?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Informazione, BusinessEntities" table="Informazioni" lazy="false">
<id name="InformazioneID" column="InformazioneID">
<generator class="identity" />
</id>

<discriminator column="TipologieInformazioneID"/>
<subclass name="Intervento, BusinessEntities" discriminator-value="0">
</subclass>

<subclass name="Criticita, BusinessEntities" discriminator-value="1">
</subclass>
</class>
</hibernate-mapping>

And the Tag class is:

public class Tag
{
private string tagID;
private IList<Informazione> informazioni = new List<Informazione>();
....
}

Here is a piece of code of the test:

// create two Tag Objects and add them an Informazione object
NHibernateSessionManager.Instance.BeginTransaction();

Criticita criticita = new Criticita();
ITagDao tagDao = daoFactory.GetTagDao();

Tag tag1 = new Tag("1234123412341234", DateTime.Now);
tag1.Informazioni.Add(criticita);
tagDao.Save(tag1);

Tag tag2 = new Tag("4321432143214321", DateTime.Now);
tag2.Informazioni.Add(criticita);
tagDao.Save(tag2);

NHibernateSessionManager.Instance.CommitTransaction();
NHibernateSessionManager.Instance.CloseSession();


//try to delete the Informazione from one object

NHibernateSessionManager.Instance.BeginTransaction();

IInformazioneDao infoDao = daoFactory.GetInformazioneDao();
Informazione informazione = infoDao.GetById(262, false);

ITagDao tagDao = daoFactory.GetTagDao();
Tag tag = tagDao.GetById("4321432143214321", false);
tag.Informazioni.Remove(informazione);

tagDao.SaveOrUpdate(tag);

NHibernateSessionManager.Instance.CommitTransaction();
NHibernateSessionManager.Instance.CloseSession();



In my test i create two Tag parent objects, add them the same children Informazione and then i remove it from the first tag List.

When i remove it from the first Tag object and save again the Tag, the relation beteween the second Tag object and the Informazione is also deleted; I think that is not expected from the cascade"all-delete-orphan" setting.

I tried to change the cascade constraint as cascade="save-update" and obviously when I remove the Informazione reference from all of the List nhibernate does not delete the record in the Informazioni table (it leaves the record "orphan" as expected).

Any idea of what is wrong with my mapping/settings?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 09, 2007 11:52 am 
Expert
Expert

Joined: Fri May 13, 2005 11:13 am
Posts: 292
Location: Rochester, NY
There is nothing wrong with what you did; this is expected behavior. NH is not smart enough (I don't think) to know whether the 'child' end of your many-to-many (*-*) still has other 'parents'. It deletes greedily.

In general, you shouldn't use a cascade more active than 'save-update' for a *-* relation, because they don't really fit the *-* semantics. 'all' and 'all-delete-orphan' are intended for parent-child relationships, where child lifetime is controlled by parent lifetime, which is generally not true for *-*.

If you want a *-* related object that is no longer linked to any others to be deleted, you'll have to implement your own 'orphan *-* deletion' routine. This could be easily done with an automatically run DB stored procedure.

I have to wonder, though: what is the behavior you are trying to acheive?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 10, 2007 5:45 am 
Newbie

Joined: Mon Jun 25, 2007 11:35 am
Posts: 15
marcal wrote:

I have to wonder, though: what is the behavior you are trying to acheive?


Hi marcal.

I'm trying to achieve the behaviour described above, that you totally understood:

If you want a *-* related object that is no longer linked to any others to be deleted, you'll have to implement your own 'orphan *-* deletion' routine. This could be easily done with an automatically run DB stored procedure.


So do you suggest to implement this behaviour in a stored procedure instead of business logic?

Kind regards

Massimo


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