-->
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.  [ 11 posts ] 
Author Message
 Post subject: using MappedSuperclass in relation one to many
PostPosted: Wed Mar 17, 2010 2:12 am 
Newbie

Joined: Thu Mar 17, 2005 5:50 am
Posts: 12
I have a hierarchy of classes as follows

Enterprise (abstract)
^
|_ Vendor
|_ Implementer
|_ Customer

each of the three subclasses have a relation one to many with class ContactPerson so I have to put three keys in ContactPerson table which always have 2 of them null

is there a way to eliminate these 3 keys and use only one key using MappedSuperclass or by any other way ?

here is my entity classes
Code:
/**
* Enterprise.java
*/
import java.io.Serializable;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;

@MappedSuperclass
public abstract class Enterprise {
   
   private String address;
   private String phone;
   private String poBox;
   private String website;

   public void setAddress(String address) {
      this.address = address;
   }
   @Column(name="ADDRESS", length=250)
   public String getAddress() {
      return address;
   }

   public void setPhone(String phone) {
      this.phone = phone;
   }
   @Column(name="PHONE", length=100 )
   public String getPhone() {
      return phone;
   }

   public void setPoBox(String poBox) {
      this.poBox = poBox;
   }
   @Column(name="POBOX", length=50)
   public String getPoBox() {
      return poBox;
   }

   public void setWebsite(String website) {
      this.website = website;
   }
   @Column(name="WEBSITE", length=50)
   public String getWebsite() {
      return website;
   }

}



Vendor.java
Code:
/**
* @(#) Vendor.java
*/
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Entity;

@Entity
@Table(name = "VENDOR")
public class Vendor extends Enterprise implements java.io.Serializable {

   private Integer id;
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   private String name;
   
   private Set contacts;

   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "vendor", targetEntity = Contact.class)
   public Set getContacts() {
      return contacts;
   }

   public void setContacts(Set contacts) {
      this.contacts = contacts;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Column(name = "NAME", length = 100, nullable = false)
   public String getName() {
      return name;
   }

}


Customer.java

Code:
/**
* @(#) Customer.java
*/
import java.io.Serializable;
import java.util.Set;
import javax.persistence.AssociationOverride;
import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name ="CUSTOMER")
public class Customer extends Enterprise implements Serializable {

   private Integer id;
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   private String name;
   
   private Set contacts;
   
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer", targetEntity = Contact.class)
   public Set getContacts() {
      return contacts;
   }

   public void setContacts(Set contacts) {
      this.contacts = contacts;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Column(name = "NAME", length = 100,nullable=false)
   public String getName() {
      return name;
   }

}


ContactPerson

Code:
/**
* @(#) ContactPerson.java
*/

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name ="CONTACT")
public class ContactPerson implements Serializable {

   private Integer id;
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   private String name;

   private String phone;

   private String email;

   private String extension;

   private String mobile;

   private String fax;

   private String title;

   private Customer customer;
   private Implementor implementor;
   
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "CUSOMER_ID")
   public Customer getCustomer() {
      return customer;
   }

   public void setCustomer(Customer customer) {
      this.customer = customer;
   }
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "IMPLEMENTOR_ID")
   public Implementor getImplementor() {
      return implementor;
   }

   public void setImplementor(Implementor implementor) {
      this.implementor = implementor;
   }
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "VENDOR_ID")
   public Vendor getVendor() {
      return vendor;
   }

   public void setVendor(Vendor vendor) {
      this.vendor = vendor;
   }

   private Vendor vendor;

   public void setName(String name) {
      this.name = name;
   }
    @Column(name="NAME", length=100,nullable=false)
   public String getName() {
      return name;
   }

   public void setPhone(String phone) {
      this.phone = phone;
   }
   @Column(name="PHONE", length=20)
   public String getPhone() {
      return phone;
   }

   public void setEmail(String email) {
      this.email = email;
   }
   @Column(name="EMAIL", length=100)
   public String getEmail() {
      return email;
   }

   public void setExtension(String extension) {
      this.extension = extension;
   }
   @Column(name="EXT", length=20)
   public String getExtension() {
      return extension;
   }

   public void setMobile(String mobile) {
      this.mobile = mobile;
   }
   @Column(name="MOBILE", length=20)
   public String getMobile() {
      return mobile;
   }

   public void setFax(String fax) {
      this.fax = fax;
   }
   @Column(name="FAX", length=20)
   public String getFax() {
      return fax;
   }

   public void setTitle(String title) {
      this.title = title;
   }
   @Column(name="TITLE", length=100)
   public String getTitle() {
      return title;
   }

   
}


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Wed Mar 17, 2010 4:37 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
I guess that mapping a ManyToOne relation towards a mapped superclass raises a mapping exception (does it?)
Anyway the thing should work if you simply declare Enterprise as abstract Entity instead as abstract MappedSuperClass

Code:
@Entity
public abstract class Enterprise
{ ...

@OneToMany(mappedBy="enterprise")
public ContactPerson contactp;

}


@Entity
public class ContactPerson
{
...

@ManyToOne
public Enterprise enterprise;
}


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Thu Mar 18, 2010 7:42 am 
Newbie

Joined: Thu Mar 17, 2005 5:50 am
Posts: 12
pb00067 wrote:
I guess that mapping a ManyToOne relation towards a mapped superclass raises a mapping exception (does it?)

there is no manytoone realtion in enterprise class(which is not mapped by a table ) this is what i want to do but don't know how
I'm not sure if it's possible so I'm asking if it's possible and how
I have 3 reference implementor - vendor - customer(which extends enterprise) in ContactPerson class

What I'm trying to do is to eliminate these 3 references and just use 1 reference to enterprise class
where to put the join column taking into consideration that Enterprise is not mapped to a table


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Thu Mar 18, 2010 9:01 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
there is no manytoone relation in enterprise class ...


But from what I undestood from your posting you intend to realize a manytoone relation TOWARDS enterprise class

Quote:
What I'm trying to do is ... just use 1 reference to enterprise class


How do you intend to map this 1 reference to enterprise class if not with a manytoone relation ?

Quote:
enterprise which is not mapped by a table

Apply the solution I proposed annotating abstract enterprise class with
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
and 'enterprise' will not be mapped by a table.

I think that is worth that you try that what I proposed.
(I already adopt this solution with success).


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Thu Mar 18, 2010 9:13 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Oh sorry, now I understand what you complained about,
here the corrected mapping:

Code:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Enterprise
{ ...

}

@Entity
public class ContactPerson
{
...

@ManyToOne
public Enterprise enterprise;
}


Now contactPerson.enterprise is just one reference which can refer either to a Vendor, Implementer or a Customer instance.


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Mon Mar 22, 2010 2:00 am 
Newbie

Joined: Thu Mar 17, 2005 5:50 am
Posts: 12
I'm not sure that you understand my problem so i will reformulate it again

problem :

3 classes (Customer - Implementor - Vendor) each have one to many relation with class ContactPerson

so in class ContactPerson I have always two null references
Code:
@Entity
@Table(name ="CONTACT")
public class ContactPerson implements Serializable {
        // two of these references are always null
   private Customer customer;
   private Implementor implementor;
   private Vendor vendor;
}
Is there any way to eliminate the 2 null references in this class taking into consideration that the three classes (Customer - Implementor - Vendor) are extending Class Enterprise which is an abstract class and is not mapped to a table


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Mon Mar 22, 2010 3:25 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
I'm not sure that you understand my problem so i will reformulate it again


And I believe indeed that it's you to not understand what I am proposing.
-You want avoid the 2 null references?
-You don't want class Enterprise being mapped to a table?

Well, then my proposal IS EXACTLY fullfiling that what you want: no null-references , no Enterprise-table on schema.

If you still doubt,
look here a example of records on the database for following scenario:
1 Customer, 1 Implementor and 1 Vendor
and each of them referred by its own contact:

Code:

-----------------------+
table.Customer          |
----+------------------+
ID  |  ...
----+------------------+
20 |   ...   
----+------------------+


-----------------------+
table.Implementor          |
----+------------------+
ID  |   ...
----+------------------+
30 |   ...
----+------------------+


-----------------------+
table.Vendor          |
----+------------------+
ID  |  ...
----+------------------+
40|   ....
----+------------------+



-----------------------+
table.Contact          |
----+------------------+
ID  |  enterprise      |
----+------------------+
1   |       20
2   |       30
3   |       40
----+------------------+




Here once again the mapping I would use, (this time more exhaustive):


Code:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Enterprise

   @Id
    id  ....

    @OneToMany(mappedBy="enterprise")
    protected Contact contact;
}


@Entity
public class Customer extends Enterprise {
..
}

@Entity
public class Implementor extends Enterprise {
..
}


@Entity
public class Vendor extends Enterprise {
..
}


@Entity
public class ContactPerson
{
  @Id ...
  id ...

@ManyToOne
public Enterprise enterprise;
}



Please give me a feedback, thanks


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Tue Mar 23, 2010 7:48 am 
Newbie

Joined: Thu Mar 17, 2005 5:50 am
Posts: 12
Thank you very much for you response
I tried it but i get only the one part of the relation inserted into DB (customer) ,
the contact is not saved
in addition to using annotation @GeneratedValue(strategy = GenerationType.AUTO) throwing exception so I have to remove it
Code:
Invocation of init method failed; nested exception is org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: Customer

here is my code
Code:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Enterprise {
   private Set<Contact> contact;
   private Integer id;
   @Id
   // @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   @OneToMany(mappedBy = "enterprise")
   public Set<Contact> getContact() {
      return contact;
   }
   public void setContact(Set<Contact> contact) {
      this.contact = contact;
   }

Customer
Code:
@Entity
@Table(name = "CUSTOMER")
public class Customer extends Enterprise implements Serializable {

   private String name;
   @Column(name = "NAME", length = 100, nullable = false)
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }

Contact
Code:
@Entity
@Table(name = "CONTACT")
public class Contact implements Serializable {
   private Enterprise enterprise;
        private String name;
   //setter getter
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "ENTERPRISE_ID")
   public Enterprise getEnterprise() {
      return enterprise;
   }
   public void setEnterprise(Enterprise enterprise) {
      this.enterprise = enterprise;
   }


Test Code
Code:
                Contact con = new Contact();
                con.setName("Amr");
               
                Set<Contact> conSet = new HashSet<Contact>();
                conSet.add(con);
                Customer cust = new Customer();
                cust.setName("MOD");
                cust.setId(3);
                con.setEnterprise(cust);
                 session.save(con )


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Wed Mar 24, 2010 3:24 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
in addition to using annotation @GeneratedValue(strategy = GenerationType.AUTO) throwing exception so I have to remove it


Yes, GenerationType.AUTO is not compatible with InheritanceType.TABLE_PER_CLASS.
You can use @Id @GeneratedValue(strategy = GenerationType.TABLE) instead (so you don't have to set the id manually).

Quote:
I tried it but i get only the one part of the relation inserted into DB (customer) ,
the contact is not saved


1. In class Contact I miss the mandatory @Id field declaration.
2. The association is bidirectional. According hibernate docu, in this case you should set both sides of the relation.
This is not happening in the snipped of the code you report as you miss to attach conSet to the customer).
3. As you don't use cascade.persist option you must persist (save) all new objects, not only contact.


revised code:

Code:
   Contact con = new Contact();
                con.setName("Amr");
               
                Set<Contact> conSet = new HashSet<Contact>();
                conSet.add(con);
                Customer cust = new Customer();
                cust.setName("MOD");

               session.save(con );
                //cust.setId(3);     not needed if you define @GeneratedValue(strategy = GenerationType.TABLE)
               session.save(cust);
               
                cust.setContact(conSet);
                con.setEnterprise(cust);
                session.getTransaction().commit();           


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Sun Apr 04, 2010 4:05 am 
Newbie

Joined: Sun Apr 04, 2010 2:21 am
Posts: 2
It work like this.

the Enterprise entity

Code:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Enterprise {

private Set<Contact> contact;
private Integer id;

   
   @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "enterprise",targetEntity=Contact.class)
   public Set<Contact> getContact() {
      return contact;
   }

   @Id
   @GeneratedValue(generator="idGen")
   @GenericGenerator(name="idGen",strategy="org.hibernate.id.IncrementGenerator")
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }

   public void setContact(Set<Contact> contact) {
      this.contact = contact;
   }

   public void setId(Integer id) {
      this.id = id;
   }

}


And the contact entity

Code:
@Entity
@Table(name = "CONTACT")
public class Contact implements Serializable {

private Enterprise enterprise;
private Integer id;

@Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "ID", unique = true, nullable = false)
   public Integer getId() {
      return id;
   }
@ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "ENTERPRISE_ID")
   public Enterprise getEnterprise() {
      return enterprise;
   }

public void setEnterprise(Enterprise enterprise) {
      this.enterprise = enterprise;
   }
}



And the customer entity

Code:
@Entity
@Table(name = "CUSTOMER")
public class Customer extends Enterprise implements Serializable {

................
      
}




and the test code

Code:
Contact contact = new Contact();
       Customer customer = new Customer();
       customer.setName("Customer Name");
       contact.setName("Test Contact Name");
       contact.setTitle("Test Contact Title");
       Set<Contact> contactSet = new HashSet<Contact>();
       contactSet.add(contact);
       contact.setEnterprise(customer);
       customer.setContact(contactSet);
session.save(customer );


Top
 Profile  
 
 Post subject: Re: using MappedSuperclass in relation one to many
PostPosted: Sun Mar 13, 2011 1:22 pm 
Newbie

Joined: Wed Mar 09, 2011 11:51 am
Posts: 1
Guys....Thank you all.. This help me lot..


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