# How to implement two entities having Composite Key?

**URL:** <https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301>\
**Category:** Hibernate ORM\
**Created:** [March 30, 2024, 1:34pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301 "2024-03-30T13:34:17Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [March 30, 2024, 1:34pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/1 "2024-03-30T13:34:17Z")

</div>

We have 3 entities: Event, EventDetail and Company.  
Both Event and EventDetail have a Composite Primary Key comprising of Sequence and Company.  
We have this because we are using Postgres and these are partitioned tables partitioned on Company, so that has to be part of the Primary Key.

Our entities looks like this, but we are getting the following exception.  
**Error:**

```auto
Caused by: java.lang.ClassCastException: org.hibernate.mapping.Formula cannot be cast to org.hibernate.mapping.Column

```

What is the right way to model these entities in Hibernate?

**Event.java**

```auto
@Entity
@Access(AccessType.PROPERTY)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Event implements Serializable {

    private Long id;
    private Company company;
    private Set<EventDetail> eventDetailSet;
    @Id
    @Column(name = "EVENT_SEQ")
    public Long getId() {
        return id;
    }

    @JoinColumn(name = "COMPANY_FK")
    @ManyToOne
    @Id
    public Company getCompany() {
        return company;
    }

    @OneToMany(cascade = CascadeType.MERGE , mappedBy = "event" )
    Set<EventDetail> getEventDetailSet()
    {
        return eventDetailSet;
    }
}

```

**EventDetail.java**

```auto
@Entity
@Access(AccessType.PROPERTY)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class EventDetail implements Serializable {

    private Long id;
    private Company company;
    private Event event;
    @Id
    @Column(name = "EVENT_DETAIL_SEQ")
    public Long getId() {
        return id;
    }

    @JoinColumn(name = "COMPANY_FK")
    @ManyToOne
    @Id
    public Company getCompany() {
        return company;
    }

    @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinColumnsOrFormulas(
            value = {
                    @JoinColumnOrFormula(column = @JoinColumn(referencedColumnName = "EVENT_SEQ", name = "EVENT_FK")),
                    @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "COMPANY_FK", value = "COMPANY_FK"))
            })
    public Event getEvent() {
        return event;
    }
}

```

---

<div class="post-metadata">

**Author:** ![mbladel](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/mbladel/32/2128_2.png) [@mbladel](https://discourse.hibernate.org/u/mbladel)\
**Post date:** [April 2, 2024, 10:52am UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/2 "2024-04-02T10:52:17Z")

</div>

Why are you using `formula = @JoinFormula(referencedColumnName = "COMPANY_FK", value = "COMPANY_FK")` instead of `column = @JoinColumn(referencedColumnName = "COMPANY_FK", name = "COMPANY_FK"))`? It looks to me like that should work fine, you don’t need any formulas here.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [April 2, 2024, 11:16am UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/3 "2024-04-02T11:16:39Z")

</div>

I suggest the following mapping instead:

```java
@Entity
@Access(AccessType.PROPERTY)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class EventDetail implements Serializable {

    private Long id;
    private Company company;
    private Long eventId;
    private Event event;

    @Id
    @Column(name = "EVENT_DETAIL_SEQ")
    public Long getId() {
        return id;
    }

    @JoinColumn(name = "COMPANY_FK")
    @ManyToOne
    @Id
    public Company getCompany() {
        return company;
    }

    @JoinColumn(name = "EVENT_FK")
    public Long getEventId() {
        return eventId;
    }

    void setEventId(Long eventId) {
        this.eventId = eventId;
    }

    @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinColumn(referencedColumnName = "EVENT_SEQ", name = "EVENT_FK", insertable = false, updatable = false),
    @JoinColumn(referencedColumnName = "COMPANY_FK", value = "COMPANY_FK", insertable = false, updatable = false)
    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        if ( event == null ) {
            this.event = null;
            this.eventId = null;
        } else {
            this.event = event;
            this.eventId = event.getId();
        }
    }

}

```

---

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [April 2, 2024, 11:26am UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/4 "2024-04-02T11:26:41Z")

</div>

@mbladel We can’t directly use JoinColumn as EventDetail already has a Company field which also uses the JoinColumn COMPANY\_FK. So Hibernate won’t allow COMPANY\_FK as another JoinColumn.

---

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [April 2, 2024, 11:31am UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/5 "2024-04-02T11:31:37Z")

</div>

@beikov Thanks for this mapping. We also moved to this mapping, but doesn’t hibernate have any other better way to map this kind of relationships?  
With more people moving to Postgres, and Postgres asking Partition Key to be part of Primary Key. We will see more such scenarios.

Also, we saw another bug in these cases in Hibernate 5.6:

**Issue** : When an Entity is having 2 JoinColumns for a @ManyToOne relationsip, even if one of the JoinColumn is null, Hibernate is creating a Proxy Object for the One side Entity.  
And if it later tries to resolve this proxy, an ObjectNotFoundException exception is thrown.

Issue Repo: [GitHub - Akshit97/hibernate-test-case-templates: Templates and examples to report issues to Hibernate](https://github.com/Akshit97/hibernate-test-case-templates)

---

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [April 2, 2024, 11:50am UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/6 "2024-04-02T11:50:28Z")

</div>

@beikov I have created a JIRA for this issue: [[HHH-17915] - Hibernate JIRA](https://hibernate.atlassian.net/browse/HHH-17915)

I think this change should fix this issue, can you please review this?  
Fix PR: [HHH-17915 - Fix Proxy Creation in case of null property by Akshit97 · Pull Request #8087 · hibernate/hibernate-orm · GitHub](https://github.com/hibernate/hibernate-orm/pull/8087)

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [April 2, 2024, 1:28pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/7 "2024-04-02T13:28:08Z")

</div>

> We also moved to this mapping, but doesn’t hibernate have any other better way to map this kind of relationships?

Unfortunately, there is no better way to model this right now.

> Also, we saw another bug in these cases in Hibernate 5.6:

[Hibernate ORM 5.6](https://hibernate.org/orm/releases/5.6/) only receives limited support at this time, so according to our [maintenance policy](https://hibernate.org/community/maintenance-policy/), there will most probably not be another release for that version family.

I suggest you to upgrade to Hibernate ORM 6.4 or later.

---

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [April 2, 2024, 1:51pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/8 "2024-04-02T13:51:55Z")

</div>

@beikov We have a legacy monolithic application running on Java 8, so upgrading to Hibernate 6 is not very straight-forward for us. We are working on the upgrade part.

But for the time-being can you please review the fix:

> <https://github.com/hibernate/hibernate-orm/pull/8087>
>
> https://hibernate.atlassian.net/browse/HHH-17915

Even if there won’t be a release for 5.6, we can create an aspect and solve the issue for us, just want your review once.  
Do you see any problems with this fix? Your review will be helpful here.

---

<div class="post-metadata">

**Author:** ![akshitagarwal](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/akshitagarwal/32/2266_2.png) [@akshitagarwal](https://discourse.hibernate.org/u/akshitagarwal)\
**Post date:** [April 2, 2024, 1:53pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/9 "2024-04-02T13:53:08Z")

</div>

@beikov Looks like this is a known issue in Hibernate 5.6

> <https://github.com/hibernate/hibernate-orm/blob/37714a6b1af5e65811eb26e951fba344c20aa303/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/formula/JoinFormulaManyToOneLazyFetchingTest.java#L93-L94>

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [April 2, 2024, 2:33pm UTC](https://discourse.hibernate.org/t/how-to-implement-two-entities-having-composite-key/9301/10 "2024-04-02T14:33:50Z")

</div>

> We have a legacy monolithic application running on Java 8, so upgrading to Hibernate 6 is not very straight-forward for us. We are working on the upgrade part.  
> Even if there won’t be a release for 5.6, we can create an aspect and solve the issue for us, just want your review once.  
> Do you see any problems with this fix? Your review will be helpful here.

I understand that, but I can’t really spend time on 5.6 unless you are a Red Hat customer and request a fix through a support ticket.
