-->
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.  [ 12 posts ] 
Author Message
 Post subject: Cascade remove fails when using delete queries
PostPosted: Thu Jun 22, 2006 5:31 pm 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
Cascade remove works fine when using s.delete(object), but not when using s.createQuery("delete from class...").executeUpdate().

Hibernate version:
Hibernate 3.2 cr2
Hibernate Annotations 3.2.0.CR1

Mapping documents:
None, used annotations only

Code between sessionFactory.openSession() and session.close():
Code:
    Transaction tx = s.beginTransaction();
    Address address = new Address();
    address.setStreetName("Privet Drive");
    address.setStreetNumber("4");
    Person person = new Person();
    person.setName("Harry Potter");
    person.setAddress(address);
    s.save(person); // should also save address
    s.flush();
    tx.commit();
    s.close();
   
    s = openSession();
    tx = s.beginTransaction();
    int retval = s.createQuery(
      "delete from " + Person.class.getName() + " where id=?"
    ).setParameters(
      new Object[] {person.getId()}, new Type[] { Hibernate.LONG }
    ).executeUpdate();
    tx.commit();



Full stack trace of any exception that occurs:
No exception occurs, object is not removed from database.

Name and version of the database you are using:
HSQL Database Engine, version: 1.7.2

The generated SQL (show_sql=true):
Hibernate: insert into Address (id, state, streetNumber, streetName, city, zip) values (null, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into Person (id, address_id_fk, name) values (null, ?, ?)
Hibernate: call identity()
Hibernate: select person0_.id as id0_1_, person0_.address_id_fk as address3_0_1_, person0_.name as name0_1_, address1_.id as id1_0_, address1_.state as state1_0_, address1_.streetNumber as streetNu3_1_0_, address1_.streetName as streetName1_0_, address1_.city as city1_0_, address1_.zip as zip1_0_ from Person person0_ left outer join Address address1_ on person0_.address_id_fk=address1_.id where person0_.id=?
Hibernate: insert into Address (id, state, streetNumber, streetName, city, zip) values (null, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into Person (id, address_id_fk, name) values (null, ?, ?)
Hibernate: call identity()
Hibernate: delete from Person where id=?
Hibernate: delete from Address where id=?
Hibernate: select address0_.id as id1_0_, address0_.state as state1_0_, address0_.streetNumber as streetNu3_1_0_, address0_.streetName as streetName1_0_, address0_.city as city1_0_, address0_.zip as zip1_0_ from Address address0_ where address0_.id=?
Hibernate: insert into Address (id, state, streetNumber, streetName, city, zip) values (null, ?, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into Person (id, address_id_fk, name) values (null, ?, ?)
Hibernate: call identity()
2006-06-22 16:03:22,805 2235 [main] WARN org.hibernate.hql.ast.tree.FromElementType - Using non-qualified column reference [id -> ([id])]
Hibernate: delete from Person where id=?
Hibernate: select person0_.id as id0_1_, person0_.address_id_fk as address3_0_1_, person0_.name as name0_1_, address1_.id as id1_0_, address1_.state as state1_0_, address1_.streetNumber as streetNu3_1_0_, address1_.streetName as streetName1_0_, address1_.city as city1_0_, address1_.zip as zip1_0_ from Person person0_ left outer join Address address1_ on person0_.address_id_fk=address1_.id where person0_.id=?
Hibernate: select address0_.id as id1_0_, address0_.state as state1_0_, address0_.streetNumber as streetNu3_1_0_, address0_.streetName as streetName1_0_, address0_.city as city1_0_, address0_.zip as zip1_0_ from Address address0_ where address0_.id=?


JUnit test case derived from hibernate-annotations-3.2.0.CR1/test/org/hibernate/test/annotations/TestCase.java:
Code:
  public void testCascadeRemoveViaQuery() {
    Session s = openSession();
    Transaction tx = s.beginTransaction();
    Address address = new Address();
    address.setStreetName("Privet Drive");
    address.setStreetNumber("4");
    Person person = new Person();
    person.setName("Harry Potter");
    person.setAddress(address);
    s.save(person); // should also save address
    s.flush();
    tx.commit();
    s.close();
   
    s = openSession();
    tx = s.beginTransaction();
    int retval = s.createQuery(
      "delete from " + Person.class.getName() + " where id=?"
    ).setParameters(
      new Object[] {person.getId()}, new Type[] { Hibernate.LONG }
    ).executeUpdate();
    tx.commit();
    s.close();
   
    s = openSession();
    tx = s.beginTransaction();
    person = (Person )s.get(Person.class, person.getId());
    assertNull("person should have been deleted", person);
    address = (Address )s.get(Address.class, address.getId());
    assertNull("address should have been deleted", address);
    tx.commit();
    s.close();
  }
 
  public Class[] getMappings() {
    return new Class[]{
      Person.class,
      Address.class
    };
  }

@Entity
public class Person extends Object implements Serializable {
  /**
   * Holds value of property name.
   */
  private String name;

  /**
   * Getter for property name.
   * @return Value of property name.
   */
  public String getName() {
    return this.name;
  }

  /**
   * Setter for property name.
   * @param name New value of property name.
   */
  public void setName(String name) {
    this.name = name;
  }

  /**
   * Holds value of property address.
   */
  private Address address;

  /**
   * Getter for property address.
   * @return Value of property address.
   */
  @OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="address_id_fk")
  public Address getAddress() {
    return this.address;
  }

  /**
   * Setter for property address.
   * @param address New value of property address.
   */
  public void setAddress(Address address) {
    this.address = address;
  }

  /**
   * Holds value of property id.
   */
  private Long id;

  /**
   * Getter for property id.
   * @return Value of property id.
   */
  @Id
  @GeneratedValue
  public Long getId() {
    return this.id;
  }

  /**
   * Setter for property id.
   * @param id New value of property id.
   */
  public void setId(Long id) {
    this.id = id;
  }
}


@Entity
public class Address extends Object implements Serializable {
  /**
   * Holds value of property streetNumber.
   */
  private String streetNumber;

  /**
   * Getter for property streetNumber.
   * @return Value of property streetNumber.
   */
  public String getStreetNumber() {
    return this.streetNumber;
  }

  /**
   * Setter for property streetNumber.
   * @param streetNumber New value of property streetNumber.
   */
  public void setStreetNumber(String streetNumber) {
    this.streetNumber = streetNumber;
  }

  /**
   * Holds value of property streetName.
   */
  private String streetName;

  /**
   * Getter for property streetName.
   * @return Value of property streetName.
   */
  public String getStreetName() {
    return this.streetName;
  }

  /**
   * Setter for property streetName.
   * @param streetName New value of property streetName.
   */
  public void setStreetName(String streetName) {
    this.streetName = streetName;
  }

  /**
   * Holds value of property city.
   */
  private String city;

  /**
   * Getter for property city.
   * @return Value of property city.
   */
  public String getCity() {
    return this.city;
  }

  /**
   * Setter for property city.
   * @param city New value of property city.
   */
  public void setCity(String city) {
    this.city = city;
  }

  /**
   * Holds value of property state.
   */
  private String state;

  /**
   * Getter for property state.
   * @return Value of property state.
   */
  public String getState() {
    return this.state;
  }

  /**
   * Setter for property state.
   * @param state New value of property state.
   */
  public void setState(String state) {
    this.state = state;
  }

  /**
   * Holds value of property zip.
   */
  private int zip;

  /**
   * Getter for property zip.
   * @return Value of property zip.
   */
  public int getZip() {
    return this.zip;
  }

  /**
   * Setter for property zip.
   * @param zip New value of property zip.
   */
  public void setZip(int zip) {
    this.zip = zip;
  }

  /**
   * Holds value of property id.
   */
  private Long id;

  /**
   * Getter for property id.
   * @return Value of property id.
   */
  @Id
  @GeneratedValue
  public Long getId() {
    return this.id;
  }

  /**
   * Setter for property id.
   * @param id New value of property id.
   */
  public void setId(Long id) {
    this.id = id;
  }
}

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 4:05 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Are you sure this is implemented - cascading on ejb-ql?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 2:42 pm 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
No, I'm not sure if it is implemented. The documentation doesn't say it is not implemented, so I assumed it was. I am working around this problem with a combination of database triggers for batch deletes and using s.delete(obj) for single objects.

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 26, 2006 6:18 pm 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Hmmm, I don't think it si trival to set up cascades on bulk deletes.
There was samo talk about implementing this behavior...

So, what do you have to complain if the mechanism isn't even implemented. :-)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 27, 2006 9:43 am 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
Well, I wasn't complaining, just pointing out a potential bug and asking for help. Also, the cascade remove works fine when using .hbm.xml schema files and <many-to-one name="whatever" cascade="all"/>, so I figured this was a annotations-only bug.

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 27, 2006 9:55 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
dillenbu wrote:
Well, I wasn't complaining, just pointing out a potential bug and asking for help.

NP. Just kidding about your complaning.

dillenbu wrote:
Also, the cascade remove works fine when using .hbm.xml schema files and <many-to-one name="whatever" cascade="all"/>, so I figured this was a annotations-only bug.

So this (cascading on bulk deletes) works for entities that are mapped my files?

Funny ...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 27, 2006 10:09 am 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
I'm not sure about the cascade working on bulk deletes, but I do know for sure it works when deleting a single object via a delete query.

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 09, 2006 7:23 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
object lifecycle is broken when you work on bulk operations. I also know we need to fix some limitations regarding associations table updates / delete and bulk operations

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 09, 2006 7:23 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I mean object lifecycle is broken by design

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 13, 2006 12:06 pm 
Beginner
Beginner

Joined: Mon Jan 09, 2006 3:05 pm
Posts: 24
Quote:
object lifecycle is broken [by design] when you work on bulk operations. I also know we need to fix some limitations regarding associations table updates / delete and bulk operations

I'm assuming the limitations regarding bulk delete operations and association tables cover this scenario: Assume Person and Group entities in a bidirectional ManyToMany relationship with Group as the owning side. This implies a Join table, with the default name of Group_Person. Currently issuing
Code:
em.createQuery("delete from Group").executeUpdate();

makes no attempt to delete the corresponding rows from Group_Person, even though Group is the owning side, giving constraint errors. Since Group_Person has no corresponding entity, I don't think the spec's prohibition on lifecycle or cascading applies here. The only workarround is to individually delete the Groups.

I couldn't find a corresponding Jira issue. Should I file one?
--keenan


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 16, 2006 1:11 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Search in Hibernate core, not HEM for the open JIRA. If there is none, then open it, thanks.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 17, 2006 2:31 pm 
Beginner
Beginner

Joined: Mon Jan 09, 2006 3:05 pm
Posts: 24
I searched and the closest I could find was HHH-1, and it didn't address bulk operations specifically, so I opened http://opensource.atlassian.com/project ... e/HHH-1917
--keenan


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