-->
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.  [ 22 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: many-to-one property-ref causing null exception
PostPosted: Thu Jul 20, 2006 8:33 pm 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
I keep getting the following error whenever I try to make my homestudycall class persitent:

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.tsc.model.order.HomestudyCall.agent
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)

My mapping's are as follows:


<hibernate-mapping package="com.tsc.model.order">
<class name="HomestudyCall" table="homestudy_call">

<many-to-one name="agent" class="com.tsc.model.user.User" column="agent_ID" property-ref="username" fetch="select" not-null="true"/>
....
</class>
</hibernate-mapping>

AND

<hibernate-mapping package="com.tsc.model.user">
<class name="com.tsc.model.user.User" table="Users">
...
<property name="username" type="string">
<column name="Username" length="32" not-null="true" />
</property>

I checked the class itself when running this, and username is set (hard coded to "hi") in the transient call class. Here's the code I use:

User user = new User();
user.setUsername("hi");
call = new HomestudyCall();
call.setAgent(user);
...
call = DAOFactory.DEFAULT.getHomestudyDAO().makePersistent(call);

And the classes were generated using the hibernateTools so it's just a setter/getter

Any help would be appreicated as I can't figure out what I'm doing wrong here. The property seems to be set to username, I'm setting username, not sure why it says it's null.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 20, 2006 10:39 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
It's not the null part that's causing this, it's the transient part. Your HomestudyCall entity is made up of lots of properties, including agent. Hibernate must be able to write agent to the DB, which means that it must be a primitive value (saved to a column), or an already-saved entity (so that its ID can be saved to a column). Neither of these are true here.

Your choices are to either save the object that goes into the agent property (the User entity) first, then put the saved User into the HomestudyCall; or to change your mapping to tell hibernate to save User objects if unsaved User entities are encountered while saving HomestudyCall objects. To do this, add cascade="save-update" or some superset of that to the many-to-one element.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 21, 2006 2:16 pm 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
Thanks...I made the user into a persistent class and it worked. But it now has a new issue. I'm using the built in listeners, so I may have to create my own, but I'm hoping I won't have to mostly because I would have no clue where to start with that kind of thing.

It gives me the following error:
SEVERE: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: collection [com.tsc.model.user.User.attributes] was not processed by flush()
at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:205)
at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:332)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:28)


the mapping file is as follows:
<hibernate-mapping package="com.tsc.model.user">
<class name="com.tsc.model.user.User" table="Users">
<map name="attributes" table="UserAttributes" lazy="true">
<key column="ownerId" not-null="true" />
<map-key column="attKey" type="string" />
<composite-element class="Attribute" >
<property name="attributeId" column="AttributeID" />
<property name="ownerId" column="OwnerId" />
<property name="attKey" column="AttKey" />
<property name="locale" column="Locale" />
<property name="datalength" column="Datalength" />
<property name="note" />
<property name="attDate" column="AttDate" />
<property name="attValue" column="AttValue" />
<property name="datatype" column="Datatype" />
<property name="fileName" column="FileName" />
<property name="mimeType" column="MimeType" />
<property name="type" column="Type" />
<property name="status" column="Status" />
</composite-element>
</map>
...

It only gives me that error if I use the user persistent class when creating the call persistent class. If, for instance, I set the agent (see previous post) property to a string type and pass in user.getUsername() it works perfectly fine. Could anyone help me w/ this? I'm fairly new to hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 23, 2006 5:52 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
You need to have an appropriate cascade level on the association from Call to User, and you need an appropriate id generator on User. Post the mappings for those bits.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 9:08 pm 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
Ok...the user id is assigned through a tokenGenerator. And the username (which is what call relates to) is assigned too.

for user:
<class name="com.tsc.model.user.User" table="Users">
<id name="id" type="string">
<column name="UserID" length="32" />
<generator class="assigned" />
</id>

for call:
<many-to-one name="agent" class="com.tsc.model.user.User" column="agent_ID" property-ref="username" fetch="select" not-null="true"/>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 9:51 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
If the ID is already assigned, then you just need to add cascade="save-update" or some superset of that to the many-to-one mapping. However, I think I remember seeing that cascades on many-to-one associations aren't behaving as expected. Can't find a JIRA about that, so maybe I'm misrecollecting.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 9:55 pm 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
But wouldn't that update my user table as well when I update the call table? I actually wouldn't want that, though I'm not really sure if it would do that or not simply because as I'm sure you can tell I'm pretty new to hibernate still.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 10:01 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
There's no cascade level for just save, only save-update, so if you want hibernate to create new users automatically, you have to let it update old users when necessary. Why wouldn't you want this funcitonality?

The only alternative is to manually save new users before saving calls that refer to them.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 24, 2006 10:10 pm 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
Users actually are the administrators taking the calls. The system doesn't have users in the sense of you or I are a user on this forum, but rather just orders taken down by administrators who are getting calls. So a user will have a whole bunch of calls, but the user does need to be created first. When a call comes in I basically load the user (which was my initial problem...the user was transient not persistent) and then save the call. But then I get that exception I mentioned where it doesn't flush it.
So I don't want the user to be saved or created or updated in regards to what the call holds. If the user doesn't exist it should throw an exception if anything (though I know the user I passed in is fine simple because I grab it one line above the setAgent method and that's fine as far as I can tell).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 12:07 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I've been labouring under a misconception then. Is it possible that you're changing the attributes collection of a persistent user? That's not allowed. You can only change the contents of the collection. So if you have code like this:
Code:
user.setAttributes(Attributes.getAppropriateAttributeSet());
You'll have to change it to look like this:
Code:
user.getAttributes().clear();
user.getAttributes().addAll(Attributes.getAppropriateAttributeSet());

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 12:22 am 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
It shouldn't be.

Basically here's the pseudo code.

user = getUserByID();
call = new call();
call.setAgent(user);
makePersistent(call);

For some reason...when it tries to end the transaction and flush everything (through that automatic mechanism that exists I guess) it throws that exception mentioned earlier.

The user does have attributes but they shouldn't be changing...at least I hope not.

Though it does have lazy loading with the attributes, and those are mapped collections to an associated table. So could that be what's doing it? But, as you noticed, it doesn't cascade updates so I didn't think that would matter.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 12:31 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
It doesn't have to cascade for the changes to be applied to the DB: the cascade influences when changes happen, but any and all changes made to persistent objects will be written to the DB during the next flush.

Can you save a user normally? If you can't, you may find that you've got something like this in your user class:
Code:
public void setAttrbiutes(Map<String, Attribute> attrs)
{
  this.attributes = new HashMap<String, Attribute>(attrs);
}
And that's just as wrong as the code in my previous post. That might cause your exception.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 12:43 am 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
Here's the code for my user class

private Map<String, Attribute> attributes = new HashMap<String, Attribute>();
private Map<String, Attribute> modules = new HashMap<String, Attribute>();
...
public Map<String, Attribute> getAttributes() {
return attributes;
}

public void setAttributes(Map<String, Attribute> attributes) {
this.attributes = attributes;
}

public Map<String, Attribute> getModules() {
return modules;
}

public void setModules(Map<String, Attribute> modules) {
this.modules = modules;
}

And yeah, if I insert a user it seems to work. The call class also works if I take out the reference to a user and just make it a String instead.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 2:15 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I'm not finding the problem. This may be beyond my ken. I don't know why the collection of composite-elements is being skipped in the flush process. Especially seeing as it probably isn't even dirty.

Sorry.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 25, 2006 2:31 am 
Beginner
Beginner

Joined: Mon Jun 19, 2006 9:21 pm
Posts: 25
Darn. Yeah, that's why I posted it on here...it's baffling me. Especially since the parts by themselves are fine, it's just when I add the user to the call. I know it has something to do w/ the fact that it's not matching up primary/foreign keys but using the prop-ref. Thanks for trying tenwit. I really appreciate the effort.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 22 posts ]  Go to page 1, 2  Next

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.