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.  [ 7 posts ] 
Author Message
 Post subject: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Mon Aug 24, 2009 10:14 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
I'm obviously not understanding something about how this works. Hopefully I can demonstrate my confusion consicely so that someone can elucidate:

I have two classes as follows:

Code:
@Entity
public class GenOne {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    long id;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "genone")
    Set<GenTwo> gentwos = new HashSet<GenTwo>();
}

@Entity
public class GenTwo {
    @Id
    @GeneratedValue (strategy = GenerationType.AUTO)
    private long id;

    private long genone;
}

I try to create a GenOne and put some GenTwos into it, thus:

Code:
            GenOne g1 = new GenOne();
            for (int i = 0; i < 3; i++) g1.gentwos.add(new GenTwo());
            session.save(g1);

On the save I get an exception, because when trying to insert a record for the first GenTwo, Hibernate sets its foreign key (genone) to zero, which fails the foreign-key constraint. I would have expected Hibernate to first insert the GenOne, get its id and then use that to fill the genone values in the GenTwo records. What am I doing wrong?

TIA

Michael

_________________
Michael Berkowitz


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Mon Aug 24, 2009 11:40 am 
Beginner
Beginner

Joined: Fri Jun 26, 2009 6:59 am
Posts: 23
try removing your @JoinColumn annotation and replacing:
@OneToMany(cascade = CascadeType.ALL)
with
@OneToMany(cascade = CascadeType.ALL, mappedBy="genone")

add @Column(name = "genone") to your attribute in GenTwo representing the foreign key.

this is how i do my unidirectional One-to-Many mappings.


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Mon Aug 24, 2009 4:23 pm 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
That sounds like it could work, and thank you for the response, but won't that make it bidirectional? There should be a way to do it as a unidirectional relationship.

_________________
Michael Berkowitz


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Mon Aug 24, 2009 5:05 pm 
Newbie

Joined: Mon Aug 24, 2009 4:59 pm
Posts: 2
Did you try to add fetch type?


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Tue Aug 25, 2009 2:34 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
I just tried it with both EAGER and LAZY, with no change in behavior.

_________________
Michael Berkowitz


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Tue Aug 25, 2009 2:51 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
I also tried your suggestion about the mapping, and threw in a Hibernate Cascade annotation for the hell of it, so now my code looks like this:

Code:
@Entity
public class GenOne {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "genone", fetch = FetchType.EAGER)
    @org.hibernate.annotations.Cascade(
            value = org.hibernate.annotations.CascadeType.ALL
    )
    Set<GenTwo> gentwos = new HashSet<GenTwo>();
}

@Entity
public class GenTwo {
    @Id
    @GeneratedValue (strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "genone")
    private long genone;
}


Still no joy. I'm now wondering whether it would work if I were to use a different key-generation strategy for GenOne, so that Hibernate won't have to get the autogenerated id back from the GenOne insertion to place into the foreign key field in GenTwo.

_________________
Michael Berkowitz


Top
 Profile  
 
 Post subject: Re: Trouble with Cascading, Unidirectional @OneToMany
PostPosted: Tue Aug 25, 2009 7:44 am 
Newbie

Joined: Mon Dec 11, 2006 8:28 am
Posts: 13
Okay, I got it now (with some help from my friend Jeremy Barkan):

Code:
@Entity
public class GenOne {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    long id;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.ALL)
    @JoinColumn(name="genone")
    Set<GenTwo> gentwos = new HashSet<GenTwo>();
}

@Entity
public class GenTwo {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
}


Hibernate adds the genone foreign-key field to the GenTwo table w/o my having to define it in GenTwo -- in fact, if I define it there that throws everything off.


So now I can get back to work, but I'd like to point two things out:

    The documentation, including 4-or-5 Hibernate books I've got, did not make any of this clear to me. I'll ask you to take my word for it that I'm not completely dense.

    Hibernate has a quirky, and very inefficient, way of doing these cascaded inserts: It first inserts the parent, then the children with uninitialized foreign keys, and then updates the foreign key of each child record in an individual update statement. The really funny thing is that if one adds a nullable = false to the JoinColumn statement, Hibernate knows to initialize the key on the insert, but it still updates it to the same value in individual updates. Here, take a look at the log:
Code:
SQL  - insert into GenOne values ( )
SQL  - insert into GenTwo (genone) values (?)
LongType  - binding '7' to parameter: 1
SQL  - insert into GenTwo (genone) values (?)
LongType  - binding '7' to parameter: 1
SQL  - insert into GenTwo (genone) values (?)
LongType  - binding '7' to parameter: 1
SQL  - update GenTwo set genone=? where id=?
LongType  - binding '7' to parameter: 1
LongType  - binding '1' to parameter: 2
SQL  - update GenTwo set genone=? where id=?
LongType  - binding '7' to parameter: 1
LongType  - binding '2' to parameter: 2
SQL  - update GenTwo set genone=? where id=?
LongType  - binding '7' to parameter: 1
LongType  - binding '3' to parameter: 2


_________________
Michael Berkowitz


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