Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary (and n-ary) relationships in Hibernate

Q 1) How can we model a ternary relationship using Hibernate? For example, how can we model the ternary relationship presented here using Hibernate (or JPA)?

NOTE: I know that JPA 2 has added some constructs for building ternary relationships using maps. However, this question assumes JPA 1 or Hibernate 3.3.x and I don't like to use maps to model this.

ER Model
(source: grussell.org)


ER Model with ternary relationships replaced
(source: grussell.org)

Ideally I prefer my model to be like this:

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Product product;
//...
}

Q 1.1)

How can we model this variation, in which each Sale item might have many Products?

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Set<Product> products;
//...
}

Q 2) In general, how can we model n-ary, n >= 3 relationships with Hibernate?

Thanks in advance.

like image 639
Behrang Avatar asked Apr 10 '10 12:04

Behrang


People also ask

What is binary and ternary relationship?

The most common types of relationships are: Unary (one entity is invloved in the relationship). Binary (two entities are involved in the relationship). Ternary (three entities are involved in the relationship)

What are the different types of relationships in JPA?

JPA Relationship TypesEditManyToOne - A reference from one object to another, inverse of a OneToMany . OneToMany - A Collection or Map of objects, inverse of a ManyToOne . ManyToMany - A Collection or Map of objects, inverse of a ManyToMany . Embedded - A reference to a object that shares the same table of the parent.

What is the relationship between JPA and Hibernate?

Hibernate is an implementation of JPA. Hence, the common standard which is given by JPA is followed by Hibernate. It is a standard API that permits to perform database operations. It is used in mapping Java data types with SQL data types and database tables.

What is ternary association?

A ternary relationship is an association among three entities. This type of relationship is required when binary relationships are not sufficient to accurately describe the semantics of the association. The ternary relationship construct is a single diamond connected to three entities as shown in Figure 2.3.


1 Answers

Q1. How can we model a ternary relationship using Hibernate? For example, how can we model the ternary relationship presented here using Hibernate (or JPA)? (...)

I would remodel the association with an intermediate entity class (and that's the recommended way with Hibernate). Applied to your example:

@Entity
public class Sale {
    @Embeddable
    public static class Pk implements Serializable {
        @Column(nullable = false, updatable = false)
        private Long soldById;

        @Column(nullable = false, updatable = false)
        private Long buyerId;

        @Column(nullable = false, updatable = false)
        private Long productId;

        public Pk() {}

        public Pk(Long soldById, Long buyerId, Long productId) { ... }

        // getters, setters, equals, hashCode
    }

    @EmbeddedId
    private Pk pk;

    @ManyToOne
    @JoinColumn(name = "SOLDBYID", insertable = false, updatable = false)
    private SaleAssistant soldBy;
    @ManyToOne
    @JoinColumn(name = "BUYERID", insertable = false, updatable = false)
    private Customer buyer;
    @ManyToOne
    @JoinColumn(name = "PRODUCTID", insertable = false, updatable = false)
    private Product product;

    // getters, setters, equals, hashCode
}

Q1.1. How can we model this variation, in which each Sale item might have many Products?

I wouldn't use a composite primary key here and introduce a PK for the Sale entity.

Q2. In general, how can we model n-ary, n >= 3 relationships with Hibernate?

I think that my answer to Q1. covers this. If it doesn't, please clarify.


Update: Answering comments from the OP

(...) the pk's fields are not getting populated and as a result I cannot save Sale items in the DB. Should I use setters like this for the Sale class? public void setBuyer(Customer cust) { this.buyer = cust; this.pk.buyerId = cust.getId(); }

You need to create a new Pk (I removed the constructors from my original answer for conciseness) and to set it on the Sale item. I would do something like this:

Sale sale = new Sale();
Pk pk = new Pk(saleAssistant.getId(), customer.getId(), product.getId());
sale.setPk(pk);
sale.setSoldBy(saleAssistant);
sale.setBuyer(customer);
sale.setProduct(product);
...

And then persist the sale.

Also, in the JoinColumn annotations, what column are "name" fields referring to? The target relations' pks or the sale table's own column names?

To the columns for the attributes of the composite Pk (i.e. the sale table's own column names), we want them to get PK and FK constraints.

like image 72
Pascal Thivent Avatar answered Oct 10 '22 10:10

Pascal Thivent