-->
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.  [ 5 posts ] 
Author Message
 Post subject: Persisting Class conversions in a Class Hierarchy
PostPosted: Wed Jan 14, 2004 8:05 pm 
Regular
Regular

Joined: Wed Jan 07, 2004 5:16 pm
Posts: 65
Location: CA, USA
Say I have a Class hierarchy, where Parent and Child both extend Person.

I have the mapping set up so that the whole hierarchy persists to one table, called Person.

I persist an instance of Person to the table.

At some point I obtain further information about this particular Person, and so now want to convert to the Parent class and persist these additional details.

I load the Person instance, and then construct an instance of Parent, passing the Person details in the constructor of Parent.

I now want to save this Parent instance.

Here's where I am having problems:

- If I try session.save(parent), this inserts a new row into the table with duplicate data except for a new generated ID and the correct new dicriminator column value for the Parent subclass type

- If I try session.saveOrUpdate(parent), this gives me this exception:
net.sf.hibernate.impl.SessionImpl Could not synchronize database state with session
TRAS0014I: The following exception was logged net.sf.hibernate.HibernateException: SQL update or deletion failed (row not found)

... presumably because it is attempting a select (before the update) on all the columns for the Parent subclass, which does not yet exist in the database.

To attempt to work around this, I have found I can delete the existing Person, and the save the new Parent instance. This works ok, but the newly inserted Parent has a new generated ID, which breaks any existing relationships that the original Person instance had.

What is the correct approach to this problem?

Thanks,
Kevin Hooke


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 14, 2004 8:33 pm 
Expert
Expert

Joined: Thu Jan 08, 2004 6:17 pm
Posts: 278
It sounds like you're trying to implement a Smalltalk "become" operation, where a single object retains its identity while changing its class.

This is not supported in Java and it makes sense that it would not be supported in Hibernate.

The cleaner thing to do would be to create your new Parent object, with a new identity, and then update all relationships to reference the new Parent object. Then delete the old Person object once it is unreferenced. (Doing all this in a single transaction, if possible, of course....)

Cheers!
Rob


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 14, 2004 9:48 pm 
Pro
Pro

Joined: Tue Aug 26, 2003 8:07 pm
Posts: 229
Location: Brisbane, Australia
Or model the whole shebang as a composite pattern:

http://forum.hibernate.org/viewtopic.php?t=926542

_________________
Cheers,
Shorn.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 16, 2004 8:12 pm 
Regular
Regular

Joined: Wed Jan 07, 2004 5:16 pm
Posts: 65
Location: CA, USA
stolley wrote:
Or model the whole shebang as a composite pattern:

http://forum.hibernate.org/viewtopic.php?t=926542


Thanks for the suggestion, but I'm not sure this scenario really fits the Composite Pattern: i.e. I don't have any object composition in a tree structure and/or need to represent this relationship as a part/whole hierarchy.

Unless I am misunderstanding the intent of the pattern?

What I am really looking for is an approach to casting instances down the class hierachy tree and updating the persisted instances accordingly:
- at some point I have a Person instance
- at a later time, I gain further information about this Person which allows me to classify them as a Parent or a Child (which are both subclasses of Person)

The only approach to this with Hibernate I have found so far is to delete the Person, instance a Parent or Child instance, and then save again in this new state.

This seems like a very clumsy approach, and I am sure there must be a better way of doing this.

Another approach would be to rework my class relationships so that this 'type' of person is an attribute of a Person, instead of a subclass, but this does not seem a very pure OO approach.

Thanks,
Kevin Hooke


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 23, 2004 2:44 pm 
Newbie

Joined: Thu Sep 09, 2004 6:50 am
Posts: 15
I'll admit that my solution to this exact problem is a hack, but here is a solution, for what its worth:

I use a joined-subclass for a setup similar to above

Person
|
-- User
|
-- Interviewer

a user may become an interviewer late in their career.

there would be hundreds of items i would need to update to delete the user and create an interviewer

so i create a simple prepared statement to add a row to the interviewer table with the appropriate id

not pretty, but it works.


Code:
    public void convertUserToInterviewer(User user) throws RAMException {
        if (user instanceof Interviewer) return;
       
        Session session = HibernateSessionFactory.currentSession();
        try {
           
            Configuration config = HibernateSessionFactory.getConfiguration();
            PersistentClass mapping = config.getClassMapping(Interviewer.class);
            String tableName = mapping.getTable().getName();
            String fieldName = "id";
            Connection connection = session.connection();
            PreparedStatement prep = (PreparedStatement) connection.prepareStatement("INSERT INTO " + tableName + "(" + fieldName + ") VALUES (?)");
            prep.setLong(1, user.getId().longValue());
            prep.execute();
           
            connection.commit();

           
           
           
        } catch (Exception e) {
            throw new DataAccessException(e);
           
        } finally {
            HibernateSessionFactory.closeSession(keepSessionOpen);
        }       
    }


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