-->
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.  [ 9 posts ] 
Author Message
 Post subject: Cascading collection of primitives only saves at flush
PostPosted: Mon Oct 03, 2005 6:04 pm 
Newbie

Joined: Wed Jan 26, 2005 11:01 am
Posts: 18
Hello,

I'm seeing strange behaviour when saving an entity with a collection of primitives (Double,String,...). When I set the cascade property to CascadeType.ALL and save the parent entity, the collection items are only inserted when the session is flushed (either explicitly or implicitly). If I change the collection to hold entities, that encapsulate the primitive, the collection items are saved eagerly (with the save of the parent entity).

Is this expected behaviour? I would expect the cascading behaviour of a collection to be the same for primitive or entity elements.

Regards,

-Maarten Winkels


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 03, 2005 6:44 pm 
Newbie

Joined: Wed Jan 26, 2005 11:01 am
Posts: 18
I tried to illumenate this with an example:

PrimitiveCollectionParent.java
Code:
package org.hibernate.test.annotations.collectionelement.cascade;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import org.hibernate.annotations.Formula;

@Entity(access=AccessType.FIELD)
public class PrimitiveCollectionParent {
   
   @Id(generate= GeneratorType.AUTO)
   private Integer Id;
   
   @OneToMany(cascade=CascadeType.ALL)
   private List<Double> scores = new ArrayList<Double>();
   
   @Formula(value="(select sum(s.elt) from PrimitiveCollectionParent_scores s where s.PrimitiveCollectionParent_Id=id)")
   private Double totalScore;
   
   public void addScore (double score) {
      scores.add(score);
   }

   public Double getTotalScore() {
      return totalScore;
   }
}


EntityCollectionParent.java
Code:
package org.hibernate.test.annotations.collectionelement.cascade;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import org.hibernate.annotations.Formula;

@Entity(access=AccessType.FIELD)
public class EntityCollectionParent {
   
   @Id(generate= GeneratorType.AUTO)
   private Integer Id;
   
   
   @OneToMany(cascade=CascadeType.ALL,mappedBy="parent")
   private List<Score> scores = new ArrayList<Score>();
   
   @Formula(value="(select sum(s.score) from Score s where s.parent_Id=id)")
   private Double totalScore;
   
   public void addScore (double score) {
      scores.add(new Score(this, score));
   }

   public Double getTotalScore() {
      return totalScore;
   }
}


Score.java
Code:
package org.hibernate.test.annotations.collectionelement.cascade;

import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

@Entity(access=AccessType.FIELD)
class Score {

   @Id(generate=GeneratorType.AUTO)
   private Integer id;
   
   @ManyToOne
   private EntityCollectionParent parent;
   
   private double score;

   public Score(EntityCollectionParent parent, double score) {
      this.parent = parent;
      this.score = score;
   }
}


PrimitiveCollectionCascadeTest.java
Code:
package org.hibernate.test.annotations.collectionelement.cascade;

import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.test.annotations.TestCase;

public class PrimitiveCollectionCascadeTest extends TestCase {

   @Override
   protected Class[] getMappings() {
      return new Class[]{PrimitiveCollectionParent.class,EntityCollectionParent.class,Score.class};
   }
   
   public final void testWithoutFlush () {
      PrimitiveCollectionParent parent = new PrimitiveCollectionParent();
      parent.addScore(13.0);
      parent.addScore(24.5);
      Session s = openSession();
      Serializable id = s.save(parent);
      s.close();
      
      s = openSession();
      PrimitiveCollectionParent persisted = (PrimitiveCollectionParent) s.get(PrimitiveCollectionParent.class,id);
      s.close();
      assertEquals(37.5,persisted.getTotalScore());
   }

   public final void testWithFlush () {
      PrimitiveCollectionParent parent = new PrimitiveCollectionParent();
      parent.addScore(13.0);
      parent.addScore(24.5);
      Session s = openSession();
      Serializable id = s.save(parent);
      s.flush();
      s.close();
      
      s = openSession();
      PrimitiveCollectionParent persisted = (PrimitiveCollectionParent) s.get(PrimitiveCollectionParent.class,id);
      s.close();
      assertEquals(37.5,persisted.getTotalScore());
   }
   
   public final void testWithEntities () {
      EntityCollectionParent parent = new EntityCollectionParent();
      parent.addScore(13.0);
      parent.addScore(24.5);
      Session s = openSession();
      Serializable id = s.save(parent);
      s.close();
      
      s = openSession();
      EntityCollectionParent persisted = (EntityCollectionParent) s.get(EntityCollectionParent.class,id);
      s.close();
      assertEquals(37.5,persisted.getTotalScore());
   }
}


As you can see the test works perfectly well when flushing or using a collection of entities. Is this due to the mappedBy property of the collection of entities? If so, I cannot specify "mappedBy"on a collection of primitives (obviously, since the primitive type will not hold a reference to the parent).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 03, 2005 7:30 pm 
Newbie

Joined: Wed Jan 26, 2005 11:01 am
Posts: 18
The assumption that the "mappedBy" property is responsible for this behaviour seems to be correct. Mapping the entity collection one-to-many unidirectionally with
Code:
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="parent_Id")
private List<Score> scores = new ArrayList<Score>();

(removing the other direction from the Score class), shows the same behaviour under flush and no flush.
This could be all due to the "mappedBy" property, but as meantioned before, how do I set this on a collection of primitives?

Cheers,

-Maarten Winkels


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 8:53 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
a collection of element has the same lifecycle of its owner entity out of the box

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 9:02 am 
Newbie

Joined: Wed Jan 26, 2005 11:01 am
Posts: 18
emmanuel wrote:
a collection of element has the same lifecycle of its owner entity out of the box


If so, shouldn't the insert statements for the collection elements be issued when 'save' is caled on the owener? As the test shows, they are not...


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 9:34 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
No, cause there is no need to retrieve eagerly an id from them

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 9:38 am 
Newbie

Joined: Wed Jan 26, 2005 11:01 am
Posts: 18
So this is a "lazy" feature for Hibernate and the fact that it breaks the formula (as the tests show) is anticipated?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 10:28 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
You have to flush before closing, that's mandatory

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 05, 2005 10:30 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
And do use transaction

_________________
Emmanuel


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