-->
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: Bi-directional one to many: PropertyValueException
PostPosted: Fri Dec 05, 2003 7:38 am 
Newbie

Joined: Fri Dec 05, 2003 7:07 am
Posts: 6
Hi folks,

I'm having trouble with a bi-directional one-to-many parent/child relationship, as discussed in Section 9 of the reference manual. I'm using hibernate-2.1rc1, and when I try to add a new child, I get this:

Code:
net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: net.sf.hibernate.persister.EntityPersister.domain
   at net.sf.hibernate.impl.SessionImpl.checkNullability(SessionImpl.java:1206)
   at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:871)
   at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:815)
   at net.sf.hibernate.impl.SessionImpl.saveWithGeneratedIdentifier(SessionImpl.java:738)
   at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:715)
   at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1317)
   at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:114)
   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:436)
   at net.sf.hibernate.engine.Cascades.cascadeCollection(Cascades.java:526)
   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:452)
   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:503)
   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:482)
   at net.sf.hibernate.impl.SessionImpl.preFlushEntities(SessionImpl.java:2552)
   at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2192)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2181)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
   at bz.clue.cluex4.daofactory.DataSource.commit(DataSource.java:42)
   ... 35 more


Here's my PostgreSQL 7.4 DDL:

Code:
CREATE TABLE Domain (
        Id              SERIAL PRIMARY KEY,
        Name         VARCHAR NOT NULL,
        CONSTRAINT      Domain_Name_ukey UNIQUE (Name)
);

CREATE TABLE Alias (
        Id              SERIAL PRIMARY KEY,
        LocalPart   VARCHAR NOT NULL,
        DomainId   INTEGER NOT NULL
                          CONSTRAINT Alias_DomainId REFERENCES Domain
                          ON DELETE CASCADE,
        CONSTRAINT      Alias_LocalPart_DomainId_ukey
                          UNIQUE(LocalPart, DomainId)
);


Here's the important stuff out of my Domain.hbm.xml and Alias.hbm.xml files:

Code:
<class name="bz.clue.cluex4.dao.Domain" table="Domain"
  dynamic-update="false"
  dynamic-insert="false">

    <id name="id" column="Id" type="java.lang.Long">
        <generator class="sequence">
            <param name="sequence">Domain_Id_seq</param>
        </generator>
    </id>
     ...
    <set name="aliases" lazy="true" inverse="true" cascade="all-delete-orphan">
        <key column="DomainId"/>
        <one-to-many class="bz.clue.cluex4.dao.Alias"/>
    </set>
</class>

<class name="bz.clue.cluex4.dao.Alias" table="Alias"
  dynamic-update="false"
  dynamic-insert="false">

    <id name="id" column="Id" type="java.lang.Long">
        <generator class="sequence">
            <param name="sequence">Alias_Id_seq</param>
        </generator>
    </id>
     ...
    <many-to-one name="domain" column="DomainId" not-null="true"/>
</class>


So now, as per Section 9, I have the following interesting classes and methods:

Code:
public class Alias implements DataAccessObject
{
    private Long id;
    private Domain domain;
    ...
    public void create()
    {
        domain.addAlias(this);
    }
    ....
}

public class Domain implements DataAccessObject
{
    private Long id;
    private Set aliases = new HashSet();
    ....
    public void addAlias(Alias alias)
    {
        alias.setDomain(this); // Not necessary in this use case, but the manual says do it
        getAliases().add(alias);
    }
}


I don't think the alias.setDomain(this) isn't necessary, because the caller is setting the domain property itself. But I stuck that in to conform with the manual.

So now in my calling code, I do this, where the DataSource class just encapsulates Session and Transaction functionality and the DomainFactory class's create() method encapsulates Session.save():

Code:
    DataSource.beginTransaction();
    Domain clue = new Domain();
    domain.setName("clue.bz");
    DomainFactory.create(clue);

    Alias root = new Alias();
    root.setLocalPart("root");
    root.setDomain(clue);
    root.create();

    DataSource.commit();


The commit() fails with the exception given above, and it's the root.create() request that triggers it. Obviously, if I don't try to establish the parent/child relationship and persist the child, the commit() works.

I should point out that I had the parent/child relationship working perfectly when I settled for establishing the relationship like this in the calling code:

Code:
    Alias root = new Alias();
    root.setLocalPart("root");
    clue.addAlias(root);


But then the caller uses FooFactory.create(foo) for some entities and parent.addChild(child) for others. I'm trying to remove this inconsistency from the caller's view.

I've read the Parent/Child section (9) very carefully, and I think I've followed it to the letter. I've checked the Users FAQ, the Latest FAQ from the Forums, and searched the old and current forum archives.

Any advice that could help me save what little hair I have left at this point would be greatly appreciated.

Thanks,
Sheldon.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 7:45 am 
Beginner
Beginner

Joined: Mon Sep 08, 2003 6:52 am
Posts: 46
I am getting the same exception thrown, except that my relationships are a one-to-one
and a many to one. I get the exception when trying to save out the guy with the one-to-one...

H


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 7:51 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Neither of you gave enough information to be useful but anyway, you should be able to find the cause yourself.

This exception occurs if a

* not-null="true" property or many-to-one or a
* constrained="true" one-to-one

references either no object, or an entity which is "unsaved".

You can avoid the case of a null reference by setting all references non-null. You can avoid the case of "unsaved" by enabling cascade save-update and making sure that all unsaved-values are set correctly.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:05 am 
Newbie

Joined: Fri Dec 05, 2003 7:07 am
Posts: 6
gavin wrote:
Neither of you gave enough information to be useful but anyway, you should be able to find the cause yourself.


I thought I'd been quite thorough. Perhaps you could let me know what information I should have provided that I didn't?

gavin wrote:
This exception occurs if a

* not-null="true" property or many-to-one or a


I assume you meant _on_ many-to-one.

That surprises me, because the manual (9.2 Bidirectional one to many) shows not-null="true" on the child's end, exactly as I've done it here.

Thing is, the child (Alias) can't exist without a parent (Domain, referenced by Alias.DomainId). The database enforces this constraint with a NOT NULL constraint.

gavin wrote:
You can avoid the case of a null reference by setting all references non-null.


This seems to contradict what you said above, so I'm not sure I'm reading your reply correctly.
I've set not-null="true" on the child's end, as shown in the manual.

Could you clarify, or explain what information you want that I didn't provide?

Thanks,
Sheldon.

PS: Sorry about the duplication of the original post. I hit submit instead of preview when I wanted to make sure I'd gotten all the code markup correct, then lost my head and hit my browser's stop button. Didn't realize the first (bad) copy had been posted.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:11 am 
Beginner
Beginner

Joined: Mon Sep 08, 2003 6:52 am
Posts: 46
gavin wrote:
Neither of you gave enough information to be useful but anyway, you should be able to find the cause yourself.

This exception occurs if a

* not-null="true" property or many-to-one or a
* constrained="true" one-to-one

references either no object, or an entity which is "unsaved".

You can avoid the case of a null reference by setting all references non-null. You can avoid the case of "unsaved" by enabling cascade save-update and making sure that all unsaved-values are set correctly.


Not-null="false" in my case
constrained="true" in my case.
cascade="save-update"

I have set all the refs to point to one another, and I'm trying to save both of them in the same operation.

I can give all the mapping snippits if you like...

H


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:16 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
if you guys really can't resolve this yourselves its going to be way quicker to just send me the code that fails in a JIRA issue and I'll find the problem.

But it should be easy to solve by putting a breakpoint in the Hibernate source on the line that throws the exception.i


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:18 am 
Newbie

Joined: Fri Dec 05, 2003 7:07 am
Posts: 6
gavin wrote:
if you guys really can't resolve this yourselves its going to be way quicker to just send me the code that fails in a JIRA issue and I'll find the problem.


Um, okay. I guess I could go that route, but I'd have to figure out how to debug into Tomcat. :-)

Could you just confirm or deny that my configuration looks sensible. I mean, should what I'm doing work?

Thanks,
Sheldon.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:30 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Could you just confirm or deny that my configuration looks sensible. I mean, should what I'm doing work?


Looks to me like you have mapped a basically uninteresting parent/child relationship. I can't really see what you are doing at the java code level, so I don't know what is wrong there.

Quote:
Um, okay. I guess I could go that route, but I'd have to figure out how to debug into Tomcat. :-)


Please let me be absolutely crystal clear on one thing: this forum is NOT a substitute for a proper test environment. No-one should EVER post here before they have exhausted all other reasonable troubleshooting options. Every extra hour we spend answering unnecessary forum traffic is an hour we could have spent developing Hibernate, improving the Hibernate documentation, finishing the book.

In fact, I refuse to provide support to anyone who is trying to develop a Hibernate application without proper unit tests. Do not post until you can reproduce your problem in a simple main() method or JUnit test.

I dunno, I know some people take this attitude the wrong way, but this just seems so reasonable to me.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:44 am 
Newbie

Joined: Fri Dec 05, 2003 7:07 am
Posts: 6
gavin wrote:
Looks to me like you have mapped a basically uninteresting parent/child relationship. I can't really see what you are doing at the java code level, so I don't know what is wrong there.


Okay. I took this to mean "Yes, I don't see anything wrong with your HBM files, and what you're doing should work, assuming you're getting all the other stuff right".

So then I took your advice and slimmed down my code. I found that the error I was getting was from a completely different relationship, the mapping for which I know is broken! So I was being a dumb-ass, basically.

I was pretty sure I was being a dumb-ass when I posted, but what I really wanted was "this looks sane, your problem's probably over there" or something.

You said you don't like helping folks who aren't doing unit testing. All well and good. In my defense, though, I _am_ doing unit testing, just not with JUnit yet. I'm using a JSP page for testing. Problem was, I was testing too much at once with that single JSP page.

But your rant about unit testing clued me in, and once I'd slimmed down the code to just the sample I showed you, it worked.

Thanks for your time. Today was headed for the rubbish bin, and you've made a good week-end possible. :-)

Ciao,
Sheldon.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 8:52 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
OK, but you see now why I get upset when people don't "slim-down" first?

It took you about 10 mins to slim down and fix the problem. I spent as long as that looking at your problem and was not able to find the cause.

Just to qualify though, I wasn't directing the rant at you in particular ... it was just a general rant against people who don't use debuggers and/or unit testing.

One of the main reasons I started Hibernate was because I was frustrated not being able to test entity beans easily. So one of the huge massive pieces of value you get from this is that you can test all your persistence logic easily, outside of the container....

anyway, its good you got the problem sorted ;)

peace


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 10:47 am 
Beginner
Beginner

Joined: Mon Sep 08, 2003 6:52 am
Posts: 46
sheldonh wrote:
...

So then I took your advice and slimmed down my code. I found that the error I was getting was from a completely different relationship, the mapping for which I know is broken! So I was being a dumb-ass, basically...


What was the broken mapping, out of curiosity? I'm still trying to track mine down...

H


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 05, 2003 10:50 am 
Newbie

Joined: Fri Dec 05, 2003 7:07 am
Posts: 6
There was no broken mapping.

I was getting that exception because of an unrelated problem, where I tried to add a completely separate kind of thing (not an Alias) for which I hadn't set an appropriate parent value. So the error message was dead-on -- I was trying to persist a child with no parent-reference.

The HBM stuff I showed works, and has been working all along. Alas, there's nothing quite like bad debugging to waste time. :-(


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.