-->
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.  [ 12 posts ] 
Author Message
 Post subject: polymorphic getter <one-to-one>
PostPosted: Wed Nov 19, 2003 2:54 pm 
Newbie

Joined: Mon Nov 17, 2003 10:53 am
Posts: 15
hi there,

i have a hopefully easy question to answer for you.
given the following code and mappings. how do i get hibernate
executing without throwing an exception.

now the classes being used
Code:
public class Job{
  private String id_;
  private String department_;
  private Employee emp_;

  public String getId{return id_;}
  public void setId(String _id){id_ = _id;}
  public String getDepartment(){return department_;}
  public void setDepartment(String _dept){department_ = _dept;}
  public Employee getEmployee(){return emp_;}
  public void setEmployee(Employee _emp){emp_ = _emp;}}

class Employee{
  private String id_;
  private String name_;

  public String getId{return id_;}
  public void setId(String _id){id_ = _id;}
  public String getName(){return name_;}
  public void setName(String _name){name_ = _name;}}

class Programmer extends Employee{
  private String prim_lang_;

  public String getPrimaryLanguage{return prim_lang_;}
  public void setId(String _prim_lang){prim_lang_ = _prim_lang;}}

class SalesPerson extends Employee{
  private String prim_cust_;

  public String getPrimaryCustomer{return prim_cust_;}
  public void setId(String _prim_cust){prim_cust_ = _prim_cust;}}


and then of course the mappings
Code:
<hibernate-mapping>
  <class name="Job" table="JOBS">
    <id name="id" column="id" type="java.lang.String">
      <generator class="uuid.hex"/>
    </id>
    <property name="department"/>
    <one-to-one
      name="employee"
      class="Employee"           
      cascade="all"/>
  </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="Programmer" table="PROGRAMMER">
    <id name="id" unsaved-value="any">
      <generator class="assigned"/>
    </id>
    <property name="name"/>
    <property name="primaryLanguage" column="PRIM_LANG"/>
  </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="SalesPerson" table="SALES_PERSON">
    <id name="id" unsaved-value="any">
      <generator class="assigned"/>
    </id>
    <property name="name"/>
    <property name="primaryCustomer" column="PRIM_CUST"/>
  </class>
</hibernate-mapping>


and here finally the table definitions
Code:
create table JOBS(
  ID CHAR (32) NOT NULL PRIMARY KEY,
  DEPARTMENT CHAR (32) NOT NULL);

create table PROGRAMMER(
  ID CHAR (32) NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL
  PRIM_LANG VARCHAR(50) NOT NULL);

create table SALES_PERSON(
  ID CHAR (32) NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL
  PRIM_CUST VARCHAR(50) NOT NULL);


here first the testcode.
Code:
Session ses = sessionFactory.openSession();
Transaction tx = ses.beginTransaction();

Job job = new Job();
job.setDepatment("Telco Supplies");

Employee emp = new Programmer();
emp.setName("robertj");
((Programmer)emp.)setPrimaryLanguage("java");

job.setEmployee(emp);

ses.save(job);
tx.commit();
ses.close();


this code will throw an exception as it tries to persist the class
Employee, which of course does not work as only the subclasses
have a persistent mapping.

any ideas how to solve this?

tia

robertj


Top
 Profile  
 
 Post subject: need <hibernate-mapping> for Employee class
PostPosted: Wed Nov 19, 2003 3:58 pm 
Regular
Regular

Joined: Sun Sep 21, 2003 11:43 pm
Posts: 85
Location: Massachusetts
I've done a one-to-one mapping and you need a <hibernate-mapping> for your Employee class. Otherwise, hibernate won't know how to save it to the database.

Regards,
David


Top
 Profile  
 
 Post subject: Re: need <hibernate-mapping> for Employee class
PostPosted: Wed Nov 19, 2003 4:05 pm 
Newbie

Joined: Mon Nov 17, 2003 10:53 am
Posts: 15
humble wrote:
I've done a one-to-one mapping and you need a <hibernate-mapping> for your Employee class. Otherwise, hibernate won't know how to save it to the database.

Regards,
David


well thats exactly the point. i dont want to save employees
to the database - only programmers or salespersons.

so i dont want/need a mapping for employee.

ciao robertj


Top
 Profile  
 
 Post subject: discriminators and subclasses probably
PostPosted: Wed Nov 19, 2003 4:16 pm 
Regular
Regular

Joined: Sun Sep 21, 2003 11:43 pm
Posts: 85
Location: Massachusetts
You wrote you don't want to save employees to the database, so why did you set your one-to-one mapping to an employee record? If you want to save the employee as a type programmer or sales_person, why don't you use subclasses with a discriminator value so they get saved to the same table since they have the same property names? The discriminator should differentiate the account type. I've tried it before but I don't have any examples handy - the ref pdf should have one though.


Why all the tables when they have the same fields?

Regards,
David


Top
 Profile  
 
 Post subject: Re: discriminators and subclasses probably
PostPosted: Wed Nov 19, 2003 4:39 pm 
Newbie

Joined: Mon Nov 17, 2003 10:53 am
Posts: 15
hi david,

Quote:
Why all the tables when they have the same fields?


this was meant as a simplified example.
but let me rephrase my question:

if i have a given set of classes
(eg. Job, Employee, Programmer, SalesPerson) AND
a given set of tables
(eg.JOBS, PROGRAMMERS, SALES_PERSON)
WHERE neither class-structure nor table-structure
is changable,

how do i create a mapping so that for a polymorphic pair
of getter/setters the correct tables will be filled when cascading
is set to true?

ciao robertj

humble wrote:
You wrote you don't want to save employees to the database, so why did you set your one-to-one mapping to an employee record? If you want to save the employee as a type programmer or sales_person, why don't you use subclasses with a discriminator value so they get saved to the same table since they have the same property names? The discriminator should differentiate the account type. I've tried it before but I don't have any examples handy - the ref pdf should have one though.
Regards,
David


Top
 Profile  
 
 Post subject: subclass or joined-subclass only work if you have a discrim.
PostPosted: Wed Nov 19, 2003 7:09 pm 
Regular
Regular

Joined: Sun Sep 21, 2003 11:43 pm
Posts: 85
Location: Massachusetts
From your included examples, I can't figure out how you determine if the employee is a programmer or a sales person. Is it one depending on which table (programmer or sales_person) you find their id number in?

A discriminator (number, character, string, anything) would be helpful to have so you could use joined-subclasses (parts of the record in different tables) based on the discriminator. My only suggestion (and since no one else has posted ideas) is to use one-to-one mappings.

If you create an employee object which has a one-to-one to the Programmer and a one-to-one to the SalesPerson, you can leave one null and one assigned. If employee.getProgrammer() != null, then you have a programmer whereas if employee.getSalesPerson() != null, then you have a Sales Person. Your account add/change logic will have to make sure one of those types is set.

I'm not skilled enough to give you an example which will assign keys for you so you could just add a "Programmer" or "SalesPerson" to your "Job" and save just the "job" but someone else probably can if you ask it in another thread.

My working example shows if you save both the Job and Programmer/SalesPerson objects individually. First, here is a Java code snippet:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
try {
tx = session.beginTransaction();
Programmer programmer = new Programmer();
Job job = new Job();
job.setDepartment("Programming");
programmer.setId(job.getId());
programmer.setName("David");
programmer.setPrimaryLanguage("Java");

session.save(job);
programmer.setId(job.getId());

session.save(programmer);
tx.commit();
session.close();
} catch (HibernateException he) {
System.out.println("Exception: " + he.getMessage() );
}
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

It came from the mapping file I made (used hbm2java and SchemaUpdate with it to create the classes and tables automatically, Hey, I'm lazy!).... Oh, I used "eg" as the package name so it won't interfere with your code if you try to test it.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
<class name="eg.Job" table="JOBS" >
<id name="id" column="id" type="string">
<generator class="uuid.hex"/>
</id>
<property name="department" type="string"/>
<one-to-one
name="programmer"
class="eg.Programmer" />
<one-to-one
name="salesperson"
class="eg.SalesPerson" />
</class>

<class name="eg.Programmer" table="PROGRAMMER">
<id name="id" unsaved-value="any" type="string">
<generator class="foreign">
<param name="property">parent</param>
</generator>
</id>
<property name="name" type="string"/>
<property name="primaryLanguage" column="PRIM_LANG" type="string"/>
<one-to-one name="parent" class="eg.Job" />

</class>

<class name="eg.SalesPerson" table="SALES_PERSON">
<id name="id" unsaved-value="any" type="string">
<generator class="foreign">
<param name="property">parent</param>
</generator>
</id>
<property name="name" type="string"/>
<property name="primaryCustomer" column="PRIM_CUST" type="string"/>
<one-to-one name="parent" class="eg.Job" />
</class>

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

I'll play around with the assigned or foreign keys for a bit and post a follow-up if I can figure them out. I'd like to know for myself but I'm just not grasping the auto-assigning cascading id's on a parent object's save.

Regards,
David


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 19, 2003 7:33 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Have you checked out the <any> mapping? This is how you map a poymorphic association to a "table-per-concrete-class" mapping strategy in Hibernate.


Top
 Profile  
 
 Post subject: but what if there's no discriminator?
PostPosted: Wed Nov 19, 2003 9:36 pm 
Regular
Regular

Joined: Sun Sep 21, 2003 11:43 pm
Posts: 85
Location: Massachusetts
Gavin,

Would the 'any' mapping work if the record has no discriminator and could be in either of two tables like Robert described?

Regards,
David


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 19, 2003 9:47 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Essentially, what the <any> mapping does is put the discriminator on the table that owns the association, instead of on the table(s) of the associated classes.

So, no, it won't map perfectly to his current schema - but it might, anyway, be what hes looking for.


Top
 Profile  
 
 Post subject: concrete any-mapping example
PostPosted: Thu Nov 20, 2003 4:50 am 
Newbie

Joined: Mon Nov 17, 2003 10:53 am
Posts: 15
hi,

ok maybe i am still not clear enough regarding my request.

all of the above is/was meant as an example.

the only real need is this:
i have a parent class that has an accessor which returns
a child class. during runtime the returned instances of
the child class will be of subclasses of this childclass but
never of the base child class.

once again an even more simplified example:

Code:
public class Job{
  ..
  public Employee getEmployee(){return emp_;}
  public void setEmployee(Employee _emp){emp_ = _emp;}}

class Employee{ .. }
class Programmer extends Employee{ .. }
class SalesPerson extends Employee{ .. }


the following rules do apply
1) the semantics of get/setEmployee must not change
2) the semantics of job to employee is a "to one" - which
does not necessarily imply that the hibernate mapping
must be that way. i quite open to suggestions.
3) cascading inserts/updates/deletes must be supported by
the mapping.
4) the class structure can be extended (not changed in their
semantics) if need to be (but i am very hesistant to do so).
5) the table structures can be extended if need to be as long
as the basic structure (3 tables, 2 for subclasses of employee)
remains.

@gavin:
i have looked into the any-mapping, but to be honest the documentation is quite shallow at the moment regarding this
mapping element. i would rather need concrete example of
the usage of any (if any is the solution).

as a side note:
the selection of the word "any" is not such a good idea imo.
i quite understand the "technical" reasoning for it and it somehow
captures the intended semantics quite well but googling for "any" is obviously useless and for looking up examples this is quite the
only way at the moment.

btw. i will have a very simmilar problem soon when using collections.
i will define something like the following (this again is only an
example).
Code:
public class Job
  public set getEmployees(){return emps_;}

in the mapping i would have to do something like this
Code:
<set name="employees" lazy="true">
  <key column="parent_id"/>
  <one-to-many class="Employee"/>
</set>

only that during runtime there never will be any Employee instances
but instances of subclasses.


if somebody can show me the concrete mappings for my example
i gladly write a small document which ties it all together.

thanks

ciao robertj


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 20, 2003 4:52 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Search for the string "<any" in the net.sf.hibernate.test package. It is what you need.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 20, 2003 4:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
oh, and for collections, there is the very-badly-named <many-to-any> element.


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