Dustin Wilhelmi
Dustin Wilhelmi

Reputation: 1829

hibernate different types of one-to-one relationships on a single class

I am trying to figure out the best way to accomplish a relationship in hibernate. I have a Customer object. Each customer has a technical contact, a billing contact, and a sales contact. Each type of contact has the exact same data structure (phone, email, address, etc).

My first thought was to create a Contact table, and then have three columns in the Customer table - sales_contact, billing_contact, technical_contact. That would make three distinct foreign key one-to-one relationships between the same two tables. However, I have found that this is very difficult to map in Hibernate, at least using annotations.

Another thought was to make it a many to many relationship, and have a type flag in the mapping table. So, any Customer can have multiple Contacts (though no more than three, in this case) and any Contact can belong to multiple Customers. I was not sure how to map that one either, though. Would tere be a type field on the map table? Would this attribute show up on the Contact java model object? Would the Customer model have a Set of Contact objects. or three different individual Contact objects?

So I am really looking for two things here - 1. What is the best way to implement this in the database, and 2. How do I make Hibernate map that using annotations?

Upvotes: 2

Views: 1970

Answers (2)

mkholod
mkholod

Reputation: 46

How about using @OneToOne and just naming the @JoinColumn differently for each type:

@Entity
public class Contact {
     @Id
     private String id;

     private String phone;
     private String email;
     private String address;

     // ... Getters and Setters
}

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private String id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="billingContact_ID")
    private Contact billingContact;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="salesContact_ID")
    private Contact salesContact;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="technicalContact_ID")
    private Contact technicalContact;

    public Customer() {
    }

    // ....
}

For each row in Customer table should create three rows in Contact table

Upvotes: 0

Yanflea
Yanflea

Reputation: 3934

It can be as simple as :

@Entity
public class Contact {
    @Id
    private String id;
    private String phome;
    private String email;
    private String address;

    // ... Getters and Setters
}

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private String id;

    @ManyToOne
    @JoinColumn(name = "ID")
    private Contact billingContact;

    @ManyToOne
    @JoinColumn(name = "ID")
    private Contact salesContact;

    @ManyToOne
    @JoinColumn(name = "ID")
    private Contact technicalContact;

    public Customer() {
    }

    // ... Getters and Setters
}

Now, if you want to make the difference between a BillingContact and a SalesContact at the object level, you can make Contact abstract, and implement it with each type of contact. You will have to annotate the parent class with @Inheritance to specify the inheritance strategy of your choice (SINGLE_TABLE sounds appropriate here, it will use a technical discriminator column - see http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1168).

Upvotes: 1

Related Questions