-->
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.  [ 8 posts ] 
Author Message
 Post subject: Cascade none (default) does not prevent updates
PostPosted: Mon Jul 02, 2007 1:55 am 
Newbie

Joined: Mon Jul 02, 2007 1:46 am
Posts: 3
Hi,
I've tried to create an object that contains a collection marked as @OneToMany and no value set for Cascade

@Entity
public class Parent {

@OneToMany
private Set<Child> children;

private Parent() {
}

1) I create a Child object and save it
2) I create a new object of type parent and set the Child in to it's collection and save the Parent
3) I update the child object
4) I save the parent object
5) I reload the child object from the database and see modified value

I thought that having no value for cascade would prevent the update to the collection's contents

Can anyone explain please?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 02, 2007 5:40 am 
Beginner
Beginner

Joined: Thu Feb 22, 2007 6:08 am
Posts: 35
Hi there.

I think that is a normal behavior. What kind o behavior were you expecting?
can you put some code?

--ms


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 02, 2007 10:39 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
I think the default for cascade is save update, so if you want nothing to happen you will need to set cascade to none explicitly.

Regards,
Jitendra
*don't forget to rate*


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 02, 2007 7:37 pm 
Newbie

Joined: Mon Jul 02, 2007 1:46 am
Posts: 3
"save-update" being the default doesn't seem to be consistent with the javadoc of the javax.persistence.OneToMany annotation. The javadoc for the optional "cascade" parameter suggests that if no value is provided (as we are doing), then there will be no cascading behaviour.

Also, there is no such "none" value for javax.persistence.CascadeType.

Any other ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 02, 2007 8:25 pm 
Beginner
Beginner

Joined: Thu Feb 22, 2007 6:08 am
Posts: 35
ca you put the code for the 5 steps? mean while, you could read the chapter 6 of the book, Java Persistence with Hibernate

--ms


Top
 Profile  
 
 Post subject: Did you update the child in attached mode
PostPosted: Tue Jul 03, 2007 12:11 am 
Regular
Regular

Joined: Wed May 02, 2007 2:42 pm
Posts: 101
If you update it when it was attached, so it update automaticly without the need to call to save.

If you will remove the save you will see that it is update althought you didnt call to save expicity.

this is the dirty -checked mechanism


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 03, 2007 9:11 pm 
Newbie

Joined: Mon Jul 02, 2007 1:46 am
Posts: 3
OK, I've finally gotten around to making a little test case for this. I have two entities: Parent and Child.

Code:
@Entity
public class Parent implements Serializable {

    private static final long serialVersionUID = 1L;
   
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    @OneToMany
    private Set<Child> children;
   
    public Parent() {
    }
   
    public Parent(String name) {
        this.name = name;
        this.children = new HashSet<Child>();
    }

    public Long getId() {
        return id;
    }
   
    public String getName() {
        return name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
   
    public void addChild(Child child) {
        this.children.add(child);
    }
   
    public Set<Child> getChildren() {
        return this.children;
    }
}


Code:
@Entity
public class Child implements Serializable {

    private static final long serialVersionUID = 1L;
   
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
   
    public Child() {
    }
   
    public Child(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
}


Now here is my test:
Code:
public class CascadeTest extends TestCase {

    private Session session;

    @Override
    protected void setUp() throws Exception {
        AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration();
        SessionFactory sessionFactory = annotationConfiguration
            .addAnnotatedClass(Parent.class)
            .addAnnotatedClass(Child.class)
            .setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect")
            .setProperty("hibernate.connection.username", "username")
            .setProperty("hibernate.connection.password", "password")
            .setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")
            .setProperty("hibernate.connection.url", "jdbc:mysql://localhost/development_db")
            .setProperty("hibernate.show_sql", "true")
            .buildSessionFactory();
        session = sessionFactory.openSession();
       
        new SchemaExport(annotationConfiguration, session.connection()).create(true, true);
    }
   
    @Override
    protected void tearDown() throws Exception {
        session.close();
    }
   
    public void testCascade() throws Exception {
        // create and save the child
        Child child = new Child("child");
        session.saveOrUpdate(child);
        session.flush();
        Long childId = child.getId();
        assertNotNull(childId);
       
        // create the parent, add the child and save the parent
        Parent parent = new Parent("parent");
        parent.addChild(child);
        session.saveOrUpdate(parent);
        session.flush();
        assertNotNull(parent.getId());
       
        // modify the child and save the parent
        child.setName("new child name");
        session.saveOrUpdate(parent);
       
        session.flush();
        session.clear();
       
        // test that the child has not been modified
        Child newChild = (Child) session.createCriteria(Child.class).add(Restrictions.eq("id", childId)).uniqueResult();
        assertEquals("child", newChild.getName());
    }
   
}


Note in the Parent class that the @OneToMany annotation is used with no cascade parameter. According to the Javadoc of that parameter, the default value for cascade is none.

As the test shows, the Child object's name is updated, the Parent is saved, then the Child is read back from the database. The test fails as the change to the Child's name has been persisted.

So here are my questions:
- Is this the expected behaviour?
- If it is the expected behaviour, is there any way to stop the Child object's change from being persisted when saving the Parent? Bear in mind that there is no such thing as CascadeType.NONE to pass to the @OneToMany annotation.
- If it is the expected behaviour, why does it go against what the javax.persistence.OneToMany annotation's javadoc says?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 04, 2007 7:58 am 
Newbie

Joined: Mon Sep 13, 2004 8:20 am
Posts: 7
Location: Poland
As avihaimar77 mentoned this is the derty check mechanism. Actually there is no cascade but on flush all changes done to objects within session are persisted. Hibernate updates your child object explicitly because it has changed within the same session and this is expected bahviour


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