-->
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.  [ 3 posts ] 
Author Message
 Post subject: creating new instance of joined subclass from parent object
PostPosted: Fri Jun 30, 2006 12:05 pm 
Newbie

Joined: Fri Jun 30, 2006 11:44 am
Posts: 3
Hello.

I have problems creating new instance of joined subclass from already existing object of superclass.

The classes in question are:

Code:
@Entity
@Table(name = "person_v")
@SequenceGenerator(name = "SEQ_STORE", sequenceName = "person_id_seq")
@Inheritance(strategy = InheritanceType.JOINED)
public class Person
{

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STORE")
    @Column(name = "person_id", nullable = false)
    long id;

    ....
}

@Entity
@Table (name = "DEBTOR")
@PrimaryKeyJoinColumn(name = "DEBTOR_ID", referencedColumnName = "PERSON_ID")
public class Debtor extends Person {

    ... some additional fields ...

}


So, Debtor extends Person and they both share primary key value. I can create entirely new Debtor without problems and have it stored in database.

Problem arises, when i already have a Person and i want to make Debtor from it without changing Person data (ie. just insert appropriate data into Debtor table). If i make new Debtor object and just copy the fields, i get

Code:
org.hibernate.WrongClassException: Object with id: null was not of the specified subclass: model.Debtor (class of the given object did not match class of persistent copy)


Any idea if such situation can be solved at all? I've looked through unit-test code, documentation and examples and i haven't seen similar problem solved anywhere. I've thought of manually inserting debtor_id into database, then load Debtor object by id, fill in the rest of the fields and persist it but there has to be a better way for doing this.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 30, 2006 1:55 pm 
Regular
Regular

Joined: Wed Jan 11, 2006 12:49 pm
Posts: 64
Location: Campinas, Brazil
Well, I guess this is more a conceptual problem. There is no such thing as "type promotion", as far as I know. So, even though a Debtor is a Person, you cannot make a Person "become" a Debtor. It is like trying to upcast a Person instance to Debtor.
Based on that, when you create a Debtor both Person and Debtor mapped tables are be populated at the same time. Think about it: if you could make a Person become a Debtor, then you could also make another Person subclass become a Debtor and you would have to keep that value into some class that extends both classes. The Java language does not allow that. Therefore it makes sense that Hibernate does not let you promote a Person to Debtor (or any subclass for that matter).
What you can do is: get the Person object, copy it to a new Debtor (detached) instance, delete the Person and save the Debtor. Or, uglier from the OO perspective, make Person-Debtor a one-to-one optional association.

_________________
Henrique Sousa
Don't forget to rate useful responses


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 01, 2006 6:19 am 
Newbie

Joined: Fri Jun 30, 2006 11:44 am
Posts: 3
Thank you for your reply.

I knew about the upcasting restriction and logically Hibernate would have no way to know from objects alone whether new Debtor was created from existing Person or not, i just thought that maybe Hibernate had some advanced workaround for that so i could manually tell it to persist Debtor fields only.

Unfortunately i can't delete existing Person, as it could be referenced from other tables and creating one-to-one relationship didn't seem that good of an idea from object model standpoint so i ended up with this (rather ugly but working) hack:

Code:

public Debtor createDebtor(final Person p)
{

        try {
            Statement stmt = getSession().connection().createStatement();
            stmt.executeUpdate("insert into debtor (debtor_id) values (" + p.getId() + ")");
            stmt.close();
        } catch (SQLException e) {
            log.error(e);
            return null;
        }

   getSession().evict(p); // REQUIRED, otherwise you get org.hibernate.WrongClassException

   Debtor d = getDebtorById(p.getId());

   saveOrUpdate(d);
   return d;
}


maybe it helps someone facing similar problem in the future.


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