-->
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.  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: one-to-one relation between two classes in the same table
PostPosted: Wed Apr 28, 2004 12:07 pm 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Hi,

I want, at the object level, to have some modularity but I have some problems to do it. I just want some advices on how I can achieve that.

Here is an example of a class I have :
Code:
public class Person
{
    private String name;
    private Integer customerNumber;
    private Integer wage;
}

But in my application I have two modules : one that manages customers and another one that manages employees. So I want to split my class in 3 different classes like that :
Code:
public class Person
{
    private String name;
}
public class Customer
{
    private Person person;
    private Integer customerNumber;
}
public class Employee
{
    private Person person;
    private Integer wage;
}

Now, the person in charge of the database tell me that he does not want to split the Person table. I have to persist my three classes in the same table : is it something doable ?

I don't think so, and I feel that if I try to do that I will run into troubles. So I want to have your opinion on this problem and possibly to have some clues on how to do it.


For me there is two way to do that :
- allow to share components
- allow to have one-to-one links between classes persisted in the same table.
Both ways seems to be impossible in the current version : why ?

Seb


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 28, 2004 12:23 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
How does the table structure look like?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 29, 2004 6:58 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Ok, so to be more precise, I did a small test.

Here are my mappings :
Code:
<class name="Customer" table="PERSON">
  <id name="id" type="integer">
    <generator class="foreign">
      <param name="property">person</param>
    </generator>
  </id>
  <property name="customerNumber" type="integer" />
  <one-to-one name="person" class="Person" constrained="true"/>
</class> 
<class name="Person" table="PERSON">
  <id name="id" type="integer">
    <generator class="increment" />
  </id>
  <property name="name" type="string" />
</class> 
<class name="Employee" table="PERSON">
  <id name="id" type="integer">
    <generator class="foreign">
      <param name="property">person</param>
    </generator>
  </id>
  <property name="wage" type="integer" />
  <one-to-one name="person" class="Person" constrained="true"/>
</class> 

so here is the table structure hibernate generates :
Code:
create table PERSON (
   id INT not null,
   name VARCHAR(255) null,
   customerNumber INT null,
   wage INT null,
   primary key (id)
)

Here is my code to do my test :
Code:
    public static void main(String[] args)
   {
        try
        {
            SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
            Session session = sessionFactory.openSession();

            Person person = new Person();
            person.setName("test");
            Customer customer = new Customer();
            customer.setCustomerNumber(new Integer(2));
            customer.setPerson(person);
            Employee employee = new Employee();
            employee.setWage(new Integer(10000));
            employee.setPerson(person);
            session.save(person);
            session.save(customer);
            session.save(employee);
            session.flush();
            session.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

and here is the stack trace of the exception I got
Code:
net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1, of class: Customer
   at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:834)
   at net.sf.hibernate.impl.SessionImpl.saveWithGeneratedIdentifier(SessionImpl.java:772)
   at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:731)
   at Test.main(Test.java:24)

I read some forum"s thread where somebody said that you could not have more thant one object in the session that point on the same row. It seems that this is the problem I have.
I just want to know why there is this restriction and if I can bypass this restriction in some way ?

Thanx, Seb


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 29, 2004 10:47 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
try "joined-subclass", I think you will have almost the same object model :

Code:
public class Person
{
    private String name;
}
public class Customer extends Person
{
       private Integer customerNumber;
}
public class Employee extends Person
{
   
  private Integer wage;
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 29, 2004 12:29 pm 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
I cannot do inheritance because the same Person can be a customer AND an employee and I don't want to have dependencies between the Customer class and the Employee class (so I can't have a two level inheritance)

seb


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 29, 2004 2:28 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Mapping multiple classes to one table is only supported with either inheritance or polymorphism="explicit"


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 6:46 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
michael wrote:
Mapping multiple classes to one table is only supported with either inheritance or polymorphism="explicit"


It is also possible with components, isn't it ?

Ok, so my question is why does hibernate have this restriction. Is it because it is something too compilcated to do due to the few cases where it can be useful ? Is it because it is not doable ? Or is it just because nobody ask for that and maybe it would be possible to do it in future versions ?

Seb


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 7:01 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Actually, it is already implemented in v22branch.

Another way to do it is to have multiple SessionFactory instances.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 7:44 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Ok thanx for the answer I will give it a try.

Just for my own understanding : how to you manage this situation ? Is it something performant ?
When I think of that I do not find an elegant way to solve the problem. Each time I create a new customer I have to do an update in the database : how hibernate knows that ? Does it do a select before to know what it has to do ?
In another case where you have two independant classes that map to the same row you have to check if there is an existing instance of the other class in the database.
If this is so, this mean that this strategy is not as effectient as the one of having one table per classe

I am right ?

seb


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 11:34 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Sorry Gavin but I downloaded the v22branch and did the test I mentioned in my previous message but I always have the NonUniqueObjectException

Seb


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 11:40 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
OH, I'm sorry, my bad. I misunderstood the question.

Code:
<class name="Person"
    polymorphism="explicit"
    table="person">
    ...
</class>

<class name="Customer"
    polymorphism="explicit"
    table="person">
    ...
    <component name="person">...</component>
</class>

<class name="Employee"
    polymorphism="explicit"
    table="person">
    ...
    <component name="person">...</component>
</class>


you might also want to check out the class-level where attribute.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 12:07 pm 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Unfortunately I tried what you told me Gavin and this does not work too. I also have a NonUniqueObjectException when I run my test.
Your proposal was very exciting because it looks like component sharing and I did not think this is possible with hibernate.
The where clause does not interest me as for each row in my table I could have one Customer instance, one Person instance and one Employee instance. I do not want to do some selection on some rows.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 30, 2004 12:10 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
WHy on earth would hyou want component sharing for. It makes no sense.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 04, 2004 4:22 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
gavin wrote:
WHy on earth would hyou want component sharing for. It makes no sense.


It is what I wrote in my first post of this topic. I want component sharing or multiple distinct classes mapped in the same table when I have modularity at the class level but not at the db level. Maybe it makes no sense as you say but I would like to have some justifications so I can argue on what I can't do it.

seb


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 04, 2004 4:26 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
A component is, by definition, non-shared. What you want is an "entity". Look up the Hibernate documentation and understand the difference between "entity" and "value type".

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


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