-->
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.  [ 14 posts ] 
Author Message
 Post subject: Hibernate: changing value of discriminator field
PostPosted: Tue Sep 28, 2004 3:26 am 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
Hibernate version: 2.1.6

Hello,

How do I change the value of discriminator field in Hibernate?
I have a hierarchy of classes:
UserVO <---- NewUser <---- IncompleteUser <------ ActiveUser

Where <---- means "extends", UserVO is an abstract class at the top of hierarchy. All these classes are mapped to the same 'user' table with discriminator field 'USER_TYPE'. Now if I have a record with 'NewUser' value in discriminator field and want to change it to 'IncompleteUser' (user status changes), how do I do that with Hibernate?

Thanks,
-Oleg.


Top
 Profile  
 
 Post subject: addition
PostPosted: Tue Sep 28, 2004 3:26 am 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
I'm using table-per-hierarchy strategy


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 3:30 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
i'm not sure to understand but you can't change an object type, so you can't change the discriminator value.
It is more (java) oo to create a new object of type 2 and delete the object of type 1.

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject: discriminator field update
PostPosted: Tue Sep 28, 2004 3:39 am 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
let me clarify my situation:

user can have different statuses:
1) "new" when he just registered
2) "incomplete" when he performs a certain action on the site
3) "active" when he does something else ,etc ...

With each successive status he has more data (more fields) associated with him.

We implement this by having a hierarchy of "user" objects, with abstract "UserVO" at the top, extended by NewUserVO, which in turn is extended by IncompleteUserVO, extended by ActiveUserVO, etc....

We do not need to change the type of an object at runtime, but we do need to change the value of the DISCRIMINATOR field from "new" to "incomplete" and later to "active" etc, so that when an object for this row is loaded NEXT time - it will be of a different type.

Here is the sequence of event:
1) Load NewUserVO from table 'user'.
2) Somehow (HOW?) update discriminator field from "new" to "incomplete"
3) some time later: load object corresponding to the same row in user table as in step 1). But this time the loaded object must be of type IncompleteUserVO (corresponding to discriminator value "incomplete".


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 3:48 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
It is possible to map a status property to the same column as the discriminator, using insert="false". You can do it that way.

If it were me, I would probably reconsider your object model. Use delegation instead of inheritance.


Top
 Profile  
 
 Post subject: insert=false does not work
PostPosted: Fri Oct 01, 2004 3:20 pm 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
I've tried doing the update using the method you suggested with mapping another property to discriminator and settting insert=false, however I'm now getting an exception:

Exception building SessionFactory: Repeated column in mapping for class ActiveUserVO should be mapped with insert="false" update="false": userType

It looks like I have to set update=false too, but then the value of the property does not get updated in the database.

Could you suggest another solution?

Thanks,
-Oleg.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 01, 2004 3:26 pm 
Beginner
Beginner

Joined: Fri Aug 13, 2004 3:07 pm
Posts: 44
I agree with anthony. In your position, I would change your design to contain a UserVO object and have an enumerated field called status. You can check the "hibernate in action" book (sample chapter available for reading online) which shows you how to do the enumerated type. Subclassing in your case is not really good design.[/i]

_________________
Thanks
Sameet


Top
 Profile  
 
 Post subject: ok
PostPosted: Fri Oct 01, 2004 3:31 pm 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
I understand that the design is probably is not done properly for Hibernate model, but our project is in the phase were we cannot make such change (switch from inheritance to delegation). I'm just looking for anywork around for this problem (updating value of the userType field).

Someone has suggested using straight JDBC to update the field, but that would compromise cached objects in Hibernate cache. Could you suggest how to get around it? Do I need to invalidate the whole cache, or is there a way to invalidate only all objects mapped to the User table, or even to a particular record?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 03, 2004 12:54 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
submit to JIRA, Hibernate should let you have the discriminator mapped to the same col as a property with insert=false


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 03, 2004 9:32 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Do you really think this is practical? Making the discriminator-field updateable would mean a type-change of the object, which is not doable in Java. This will produce all kinds of nasty conflicts ...

Code:
A a = session.load(12);
a.setType("B");
s.flush();
B b = session.load(12);
// conflict


The object should now be of type B, however there is still an old A instance with the same identifier around.

IMHO the only clean way to do this is to use JDBC and to manually flush the caches.


Top
 Profile  
 
 Post subject: JDBC update
PostPosted: Sun Oct 03, 2004 9:57 pm 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
That is precisely what I'm trying to do now, straight JDBC - then flush the caches, but it looks like Session.evict(Object) and Session.getSessionFactory().evict(...) methods are not completely flushing caches, because I'm still getting the NonUniqueObjectException, with the message that there are two objects mapping to the same id.

I'm getting this error only when I'm trying to update the second object, of the updated type (IncompleteUserVO).

Here is the sequence:
1) Load NewUserVO from user table.
2) get its id and call JDBC to update the discriminator field 'userType' to 'incomplete'. Evict old object (NewUserVO) from Hibernate cache.
3) Load user object with the same id - now Hibernate loads an instance of IncompleteUserVO (which is good), with all data.. everything ok
4) When I'm changing value of one of the fields on IncompleteUserVO and trying to update it using Session.update(..) - I'm getting NonUniqueObjectException

Here is the code that does the JDBC update and cleans Hibernate cache. Is there anything wrong with it?

--------------------
NewUserVO user = ...
int id = user.getId();
Class clazz = user.getClass();
Connection conn = session.connection();
Statement stat = conn.createStatement();
session.flush();
session.getSessionFactory().evict(clazz, new Integer(id));
session.evict(user);
int result = stat.executeUpdate("update user set userType = 'incomplete' where id = " + id);
if (!conn.getAutoCommit())
conn.commit();
session.getSessionFactory().evict(clazz, new Integer(id));
session.evict(user);

IncompleteUserVO inuser = new IncompleteUserVO();
session.load(inuser, new Integer(id));
--------------------

As I said - the session.load method loads 'inuser' with valid data, but whenever I'm trying to do session.update(inuser) - I'm getting that exception.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 03, 2004 10:06 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Continuing to use a session which has an already committed connection is not a good idea anyways. Use a new session.


Top
 Profile  
 
 Post subject: clarification
PostPosted: Sun Oct 03, 2004 10:20 pm 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
could you post a code sample of what I need to do? just session.close() ?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 03, 2004 11:25 pm 
Newbie

Joined: Tue Apr 13, 2004 4:27 pm
Posts: 9
also, what if other thread's sessions are keeping a reference to that record through objects of type NewUserVO?


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