-->
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.  [ 20 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Delete cascading not working for OneToOne
PostPosted: Wed Apr 16, 2008 3:52 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hibernate version:
3.2.6
Name and version of the database you are using:
MySQL 5.0.1 (Hibernate is configured for MySQL5InnoDB dialect)

Hello,
I've got a simple OneToOne relationship between Site and SiteRuntime entities (PKs are not shared or anything like that), where SiteRuntime contains some info aboud Site.

My use case is simple:
Code:
Site site = new Site();
SiteRuntime rt = new SiteRuntime();
site.setRuntime(rt);
rt.setSite(site);
em.persist(site); //ok

And later, in a different transaction:
Code:
em.createQuery("delete from Site s where s.name='text'").executeUpdate(); // exception, see below.


The exception:
Code:
javax.persistence.EntityExistsException: org.hibernate.exception.ConstraintViolationException: could not execute update query
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:612)
        at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:58)
...
Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db1/site_runtime`, CONSTRAINT `FK2627A2C06DE06746` FOREIGN KEY (`SITE_ID`) REFERENCES `site` (`SITE_ID`))
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1011)
...


I also verified that "ON DELETE CASCADE" is NOT added at the db level - bad news since I do bulk deletion which will fail without it. BUT: if the relationship between Site and SiteRuntime was OneToMany, the db schema DOES contain "ON DELETE CASCADE" and all is OK.

Any ideas what I'm doing wrong?

Here are the entities:
Code:
@Entity
public class Site implements Serializeable {
   
    public Site() {}

    @Id @GeneratedValue @Column(name = "SITE_ID", nullable = false)
    private Long id;
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
   
    @Column(name = "SITE_NAME", nullable = true)
    private String name;
    public String getName() { return this.name; }
    public void setName(String siteName) { this.name = siteName; }

// if I change the relationship below to OneToMany, all is OK,
// but then I'm forced to change the type of the member to some
// collection, and I wish to avoid that...   
    @OnDelete(action=OnDeleteAction.CASCADE)
    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="site")
    private SiteRuntime runtime;
    public SiteRuntime getRuntime() { return runtime; }
    public void setRuntime(SiteRuntime runtime) { this.runtime = runtime; }
...
}


@Entity
public class SiteRuntime implements Serializeable {
   
    public SiteRuntime() {
    }
   
    @Id
    @GeneratedValue
    @Column(name = "SITE_RUNTIME_ID", nullable = false)
    private Long id;
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
   
   
    @OneToOne(fetch = FetchType.LAZY, optional=false)
    @JoinColumn(name="SITE_ID", nullable=false)
    private Site site;
    public Site getSite() { return site; }
    public void setSite(Site site) {
        this.site = site;
        if (site != null) this.siteId = site.getId();
    }

    @Column(name="SITE_ID", nullable=false, insertable=false, updatable=false)
    private Long siteId;
    public Long getSiteId() { return siteId; }
    public void SiteId(Long siteId) { this.siteId = siteId; }

...
}


Top
 Profile  
 
 Post subject: Did you try to call to em.remove
PostPosted: Thu Apr 17, 2008 6:03 pm 
Beginner
Beginner

Joined: Mon Apr 07, 2008 12:49 pm
Posts: 33
try to see if this work.
why you need OnDelete annotation? you have it in the cascade.all


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 18, 2008 4:29 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

A possible casue is that Site is the non-owning side of the relationship, so it cannot update the DB. You could try swapping the owning sides (non-owning designated by mappedBy), or calling SiteRuntime.setSite(null) before removing the site.

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject: I'll answer last 2 comments
PostPosted: Sun Apr 20, 2008 4:43 pm 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
1. Cascade.REMOVE/ALL do not generate an ON DELETE CASCADE declaration at db level and thus do not apply for bulk delete operations, which is why I need the OnDelete annotation, that should instruct Hibernate (according to the doc) to declare db-level cascading. e.g. em.remove(id) will cascade without OnDelete, but "delete entity e where e.id = 1" will not cascade without OnDelete.

2. I have tried switching relationship owners - it didn't help.

Next, I'll try switching to hbm files instead of annotations - maybe there's better support there. I'll update this thread once I get to it. I'd appreciate any additional comments if someone has more ideas.

thanks....


Top
 Profile  
 
 Post subject: updates
PostPosted: Mon Apr 21, 2008 4:22 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hi,
I have some updates:
I have tested the option of using .hbm files instead of annotations, but it doesn't seem to help. I've followed the Hibernate doc about "one-to-one unique FK association" to the letter and still, bulk delete operations do not cascade! I'm not sure whether it's because I'm trying this via JPA, or because I'm doing something wrong, or because there is no support of bulk operation cascading in such a case...

My persistence.xml contains the following property, to ensure correct pick up of hbm files:
Code:
<property name="hibernate.archive.autodetection" value="hbm"/>


My entity and hbm files for Item and ItemInfo (represent Site and SiteRuntime respectively):
Code:
public class Item implements Serializable {
    private Long id;
    public Long getId() { return this.id; }
    public void setId(Long id) { this.id = id; }
   
    private ItemInfo itemInfo;
    public ItemInfo getItemInfo() { return itemInfo; }
    public void setItemInfo(ItemInfo itemInfo) { this.itemInfo = itemInfo; }
}

<class name="pu1.Item" table="ITEM">
    <id name="id" column="ITEM_ID">
        <generator class="native"/>
    </id>
    <one-to-one name="itemInfo" property-ref="item" cascade="all" />
</class>

public class ItemInfo implements Serializable {
    private Long id;
    public Long getId() { return this.id; }
    public void setId(Long id) { this.id = id; }

    private Item item;
    public Item getItem() { return this.item; }
    public void setItem(Item item) { this.item = item; }
}

<class name="pu1.ItemInfo" table="ITEM_INFO">
    <id name="id" column="ITEM_INFO_ID">
        <generator class="native"/>
    </id>
    <many-to-one name="item" column="ITEM_ID" unique="true"/>
</class>


Once the project is deployed, this is the DDL that is generated. Note there is no ON DELETE CASCADE declaration:
Code:
CREATE TABLE  `test`.`item` (
  `ITEM_ID` bigint(20) NOT NULL auto_increment,
  PRIMARY KEY  (`ITEM_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

CREATE TABLE  `test`.`item_info` (
  `ITEM_INFO_ID` bigint(20) NOT NULL auto_increment,
  `ITEM_ID` bigint(20) default NULL,
  PRIMARY KEY  (`ITEM_INFO_ID`),
  UNIQUE KEY `ITEM_ID` (`ITEM_ID`),
  KEY `FK2836965A74280EDC` (`ITEM_ID`),
  CONSTRAINT `FK2836965A74280EDC` FOREIGN KEY (`ITEM_ID`) REFERENCES `item` (`ITEM_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;


pls advise,
thank you.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 21, 2008 6:19 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

Have you tried to remove a single Site with the EntityManager.remove() ? If you have not could please try and then report what happens.

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject: yes
PostPosted: Mon Apr 21, 2008 8:30 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
When calling em.remove(instance), there were never any issues - it works great. The problem only shows up when performing bulk ops with queries, e.g. "delete s from Site s where s.name like '%ss%'' and so on. And again: if the relationship was 1:N instead of 1:1, the ON DELETE CASCADE delcaration is added to the schema, bulk ops work like a charm, the PU cache stays in sync even after the operation, etc. The problem only occurs for 1:1 relationships :-(


Top
 Profile  
 
 Post subject: As far as i know
PostPosted: Mon Apr 21, 2008 9:37 am 
Beginner
Beginner

Joined: Mon Apr 07, 2008 12:49 pm
Posts: 33
AS far as i know hibernate dosnt add on delete to the DDL, it take care for it.
it sound starnge what you say that hibernate add it


Top
 Profile  
 
 Post subject: on delete cascade
PostPosted: Mon Apr 21, 2008 10:03 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Of course hibernate adds it, as long as you specify @OnDelete annotation.


Top
 Profile  
 
 Post subject: I work with JPA
PostPosted: Mon Apr 21, 2008 11:04 am 
Beginner
Beginner

Joined: Mon Apr 07, 2008 12:49 pm
Posts: 33
i just use the cascade , dont need ondelete


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 22, 2008 3:53 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

I just did a little testing this morning and refactored the entities you posted to make the Site the owning side of the releationship means this query now works:

Code:
em.createQuery("delete from Site s where s.name='text'").executeUpdate();

however you will now get into problems if you try to bulk delete from the SiteRuntime.

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject: retried that
PostPosted: Tue Apr 22, 2008 5:29 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hi Andy,
I just tried the same... seems like this time the query exectues without error, but the SiteRuntime entity remains in the database after the query is complete... Did you get the same result?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 22, 2008 6:03 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

Yes i get the same result as you. If you want both to be deleted I think you are best switching to a OneToMany relationship, as you stated that it works as is expected.

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 22, 2008 6:25 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

I have got it working now ;-) If you define @OnDelete on both sides of the relationship, or at least on the owning side (SiteRuntime in your case). You can now delete from Site and it will delete the referenced SiteRuntime

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject: interesting....
PostPosted: Tue Apr 22, 2008 6:55 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
hmmmm. ok, I'll give it a try once I get a chance. I wonder what's the rationale behind this... I'll update the thread tomorrow. thanks for the help.


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

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.