-->
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: Join Table with Collection of Components Cascade Issue
PostPosted: Wed Feb 13, 2008 1:35 pm 
Beginner
Beginner

Joined: Fri Jan 26, 2007 3:16 pm
Posts: 24
Hi, I'm following the example in the the Java Persistence With Hibernatebook on p. 307 "Mapping the join table to a collection of components. Below, I have a QPolicy class which can have a number of QRules assigned to it. There is an intermediate association class between a QPolicy and a QRule called QPolicyRule that also contains a severity. I've annotated it precisely how the book lists, which is supposed to manage cascades for me automatically. However, if I write the following code:

Code:
EntityTransaction tx = em.getTransaction();
QPolicy policy = new QPolicy(...);
policy.addRule(new QRule(...));
tx.begin();
em.persist(policy);
tx.commit();


What I'm expecting is that hibernate will create a new row in QPolicy table, a new row in QPolicyRule, and a new row in QRule table. What actually happens is that hibernate creates a new row in QPolicy, QPolicyRule, and then throws an exception complaining that QRule is transient and that I must persist that object separately first.

But this is precisely the whole reason for embedding the collection of components, as the book clearly states:

Quote:
The advantage of a collection of components is clearly the implicit lifecycle of the link objects. To create an association between a Category (QPolicy) and an Item (QRule), ad a new CategorizedItem (QPolicyRule) instance to the collection. To break the link, remove the element from the collection. No extra cascading settings are required, and the Java code is simplified.


What am I missing here?

Hibernate version:
hibernate-3.2.4.ga
hibernate-commons-annotations-3.0.0.ga
hibernate-entitymanager-3.3.1.ga
hibernate-annotations-3.3.0.ga

Mapping documents:
Code:
@Entity
@Table(name="QPOLICY")
public final class QPolicy {

     /** The set of associations with Rules for this policy. */
    @org.hibernate.annotations.CollectionOfElements
    @JoinTable(name = "QPOLICY_QRULE", joinColumns = @JoinColumn(name = "QPOLICY_ID"))
    private Set<QPolicyRule> policyRules = new HashSet<QPolicyRule>();
}


Code:
@Embeddable
public final class QPolicyRule {

    /** The QPolicy that is part of this association. */
    @org.hibernate.annotations.Parent
    private QPolicy QPolicy;

    /** The rule that is part of this association. */
    @ManyToOne
    @JoinColumn(name = "QRULE_ID", nullable = false, updatable = false)
    private final QRule rule;

    /** The severity of this rule in the context of this QPolicy. */
    @Enumerated(EnumType.STRING)
    @Column(name = "SEVERITY", nullable = false, updatable = false)
    private final Severity severity;
}


The class QRule has no interesting mappings that are relevant, as it has no direct associations to QPolicy or QPolicyRule

Full stack trace of any exception that occurs:
Quote:
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.qcommon.repository.QRule
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:87)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:307)


Name and version of the database you are using:
hsqldb-1.8.0.7

The generated SQL (show_sql=true):

Code:
Hibernate:
    insert
    into
        QPOLICY
        (AUTO_VERSION, DESCRIPTION, NAME, role, VERSION, QPOLICY_ID)
    values
        (?, ?, ?, ?, ?, ?)


Code:
Hibernate:
    insert
    into
        QPOLICY_QRULE
        (QPOLICY_ID, QRULE_ID, SEVERITY)
    values
        (?, ?, ?)


Note that it does not do the insert into the QRULE table, the next thing I get in the log debug is the exception complaining that the QRule object is transient. I know the object is transient, but I thought what the book describes would manage it in a cascading style.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 13, 2008 6:15 pm 
Beginner
Beginner

Joined: Fri Oct 06, 2006 2:49 am
Posts: 25
Hello Davis,

Your right my problem seems to be similar to yours because I did not rewrite properly my classes :(

http://forum.hibernate.org/viewtopic.php?p=2376516#2376516

In fact, originally I rewrite my problem to be brief on the forum and I forgot to mention the annotation cascade on Child.element. I reply as you will see on the post to correct this.

In your side, therefore I advise you to test this:

Code:
@Embeddable
public final class QPolicyRule {

    /** The QPolicy that is part of this association. */
    @org.hibernate.annotations.Parent
    private QPolicy QPolicy;

    /** The rule that is part of this association. */
    @ManyToOne(cascade=Cascade.ALL)
    @JoinColumn(name = "QRULE_ID", nullable = false, updatable = false)
    private final QRule rule;

    /** The severity of this rule in the context of this QPolicy. */
    @Enumerated(EnumType.STRING)
    @Column(name = "SEVERITY", nullable = false, updatable = false)
    private final Severity severity;
}



Tell me if it works like that...

Tiggy



[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 14, 2008 12:09 pm 
Beginner
Beginner

Joined: Fri Jan 26, 2007 3:16 pm
Posts: 24
Tiggy, this does not fix the problem.

From the quote I indicated above (from book p. 309) --

Quote:
No extra cascading settings are required, and the Java code is simplified


Indeed, even if I change the mapping to this:

Code:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="QRULE_ID", nullable=false, updatable=false)
private final QRule rule;


For PolicyRule class, it still does not work. I'm beginning to think that the semantics of hibernate here are that it will not cascade operations to the other end of the association class.

Thus, in this example, a commit to QPolicy will cascade operations only to PolicyRule, but not QRule.

Unless someone can tell me otherwise?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 14, 2008 5:00 pm 
Beginner
Beginner

Joined: Fri Oct 06, 2006 2:49 am
Posts: 25
I think you misunderstood the comment in the book.

No extra cascading settings are required, and the Java code is simplified

The comment of the book is right for a component, it follow the life cycle of its parent => no cascading rule need to be define, it makes sense ;)

But here we are talking about an association in a component => you need to specify the cascading rules. The comment did not say that the cascade will be propagated to all the elements in a component... right ?

The last thing I can advise you is to simplify your mapping:
- I am not sure that Hibernate support well final field
- Secondly I think you should try to remove updatable="false". Normally this should not have any effect on insertion because you did not put insertable="false"

please try it.... and tell us if this makes any difference

Code:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="QRULE_ID", nullable=false)
private QRule rule;


Good luck for testing ;)
Tiggy
[/i]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 20, 2008 8:12 pm 
Beginner
Beginner

Joined: Fri Oct 06, 2006 2:49 am
Posts: 25
any news for that ?

is it working now ?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 21, 2008 9:35 am 
Beginner
Beginner

Joined: Fri Jan 26, 2007 3:16 pm
Posts: 24
Hi Tiggy, removing final and updatable does not change the outcome.

I abandoned trying to solve this problem.

From a business-logic perspective, I decided I don't want cascading to happen from policy to rule. Rules should be managed independent of policy.

It would be nice if someone that knew the answer could just say yes or no whether it <i>should</i> work, or whether I'm misinterpreting the book and the API.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 21, 2008 1:19 pm 
Newbie

Joined: Tue Feb 19, 2008 10:25 pm
Posts: 5
I'm having this exact same problem, just with hibernate 2.

My join table entity objects are saving to the database, but are seen by hibernate as transient instances.

The interesting thing is that i only get this problem in the web tier, but not in the unit test case. Something with the differing transaction handling must be throwing things off, but I just don't know.

I'm about to give up too.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 28, 2008 12:01 pm 
Newbie

Joined: Fri Mar 28, 2008 9:08 am
Posts: 3
Related posts:
http://forum.hibernate.org/viewtopic.php?t=983766
http://forum.hibernate.org/viewtopic.php?t=976534


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.