# How to map a Many-To-One relationship with multiple target entities with JPA and Hibernate

**URL:** <https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761>\
**Category:** Hibernate ORM\
**Created:** [November 21, 2018, 1:59pm UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761 "2018-11-21T13:59:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hedza06](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/hedza06/32/844_2.png) [@hedza06](https://discourse.hibernate.org/u/hedza06)\
**Post date:** [November 21, 2018, 1:59pm UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761/1 "2018-11-21T13:59:31Z")

</div>

Hello everyone,  
I’m trying to map column to multiple target entities and trying to define a relationship many-to-one.

I have a column in my table that can be foreign key on multiple tables. Let call that column channel. If channel type is 1 then I need to fetch entity A (channel), and if channel\_type is 2 then I have to fetch entity B (channel).

Is this possible to do in hibernate?

Thank you in advance.

---

<div class="post-metadata">

**Author:** ![vlad](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/vlad/32/658_2.png) [@vlad](https://discourse.hibernate.org/u/vlad)\
**Post date:** [November 21, 2018, 5:00pm UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761/2 "2018-11-21T17:00:22Z")

</div>

Check out the [`@Any` annotation](http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#mapping-column-any) for this task.

---

<div class="post-metadata">

**Author:** ![hedza06](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/hedza06/32/844_2.png) [@hedza06](https://discourse.hibernate.org/u/hedza06)\
**Post date:** [November 21, 2018, 9:19pm UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761/3 "2018-11-21T21:19:32Z")

</div>

@vlad thank you. Can you please check this code, I have error:

ChannelType.java

```auto
package com.tips.hibernate.entities;

import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "channel_type")
@DynamicInsert
@DynamicUpdate
public class ChannelType implements Serializable {

    private static final long serialVersionUID = 20181121211300L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, updatable = false)
    private Long id;

    @Column(name = "code", nullable = false, unique = true)
    private String code;

    @Column(name = "description")
    private String description;

    public Long getId() {
        return id;
    }

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

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

```

Call.java

```auto
package com.tips.hibernate.entities;

import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "call")
@DynamicInsert
@DynamicUpdate
public class Call implements Serializable, Channel {

    private static final long serialVersionUID = 20181121212000L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, updatable = false)
    private Long id;

    @Column(name = "duration", nullable = false)
    private Long duration = 0L;

    @Column(name = "target_phone", nullable = false)
    private String targetPhone;

    @Column(name = "comment")
    private String comment;

    @Column(name = "status", nullable = false)
    private String status = "handled";

    @Column(name = "description")
    private String description;

    public Long getId() {
        return id;
    }

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

    public Long getDuration() {
        return duration;
    }

    public void setDuration(Long duration) {
        this.duration = duration;
    }

    public String getTargetPhone() {
        return targetPhone;
    }

    public void setTargetPhone(String targetPhone) {
        this.targetPhone = targetPhone;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

```

Sms.java

```auto
package com.tips.hibernate.entities;

import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "sms")
@DynamicInsert
@DynamicUpdate
public class Sms implements Serializable, Channel {

    private static final long serialVersionUID = 20181121211500L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, updatable = false)
    private Long id;

    @Column(name = "target_phone", nullable = false)
    private String targetPhone;

    @Column(name = "comment")
    private String comment;

    @Column(name = "status", nullable = false)
    private String status = "unknown";

    @Column(name = "description")
    private String description;

    public Long getId() {
        return id;
    }

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

    public String getTargetPhone() {
        return targetPhone;
    }

    public void setTargetPhone(String targetPhone) {
        this.targetPhone = targetPhone;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

```

Interaction.java

```auto
package com.tips.hibernate.entities;

import org.hibernate.annotations.*;

import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name = "interaction")
@DynamicInsert
@DynamicUpdate
@SuppressWarnings("squid:S1948")
@AnyMetaDef(
    name = "ChannelMetaDef", idType = "long", metaType = "string",
    metaValues = {
            @MetaValue(targetEntity = Call.class, value = "call"),
            @MetaValue(targetEntity = Sms.class, value = "sms")
    }
)
public class Interaction implements Serializable {

    private static final long serialVersionUID = 20181121214100L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, updatable = false)
    private Long id;

// @ManyToOne
// @JoinColumn(name = "channel_type_id", nullable = false)
// private ChannelType channelType;

    @Any(
        metaColumn = @Column(name = "channel_type_id"),
        metaDef = "ChannelMetaDef",
        fetch = FetchType.EAGER
    )
    @JoinColumn(name = "channel_id", nullable = false)
    private Channel channel;

    @Column(name = "description")
    private String description;

    @Column(name = "created_at", nullable = false)
    private Date createdAt;

    public Long getId() {
        return id;
    }

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

// public ChannelType getChannelType() {
// return channelType;
// }
//
// public void setChannelType(ChannelType channelType) {
// this.channelType = channelType;
// }

    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    @Override
    public String toString()
    {
        return "Interaction{" +
                "id=" + id +
                ", channel=" + channel +
                ", description='" + description + '\'' +
                ", createdAt=" + createdAt +
                '}';
    }
}

interface Channel {
    String getTargetPhone();
}

```

Interaction schema:

```auto
<changeSet id="interaction" author="hedza06" context="dev, prod">
        <createTable tableName="interaction">
            <column name="id" type="int" autoIncrement="${autoIncrement}">
                <constraints nullable="false" primaryKey="true" />
            </column>
            <column name="channel_type_id" type="bigint">
               <constraints nullable="false"/>
            </column>
            <column name="channel_id" type="bigint">
                <constraints nullable="false"/>
            </column>
            <column name="description" type="varchar(255)">
                <constraints nullable="true"/>
            </column>
            <column name="created_at" type="timestamp" defaultValueDate="${now}"/>
        </createTable>
        <!-- Add foreign key on channel_type -->
        <addForeignKeyConstraint
                baseTableName="interaction"
                baseColumnNames="channel_type_id"
                constraintName="fk_interaction_channel_type_id_key"
                referencedTableName="channel_type"
                referencedColumnNames="id" />
    </changeSet>

```

When I tried to fetch all interaction it returns null for channel. Channel can be Sms or Call depends on ChannelType.java (column code which is string - unique).

---

<div class="post-metadata">

**Author:** ![vlad](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/vlad/32/658_2.png) [@vlad](https://discourse.hibernate.org/u/vlad)\
**Post date:** [November 21, 2018, 10:18pm UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761/4 "2018-11-21T22:18:03Z")

</div>

Try to debug it and see why it does not work for you. You can find a working example in the Hibernate ORM test cases.

---

<div class="post-metadata">

**Author:** ![vlad](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/vlad/32/658_2.png) [@vlad](https://discourse.hibernate.org/u/vlad)\
**Post date:** [November 28, 2018, 6:15am UTC](https://discourse.hibernate.org/t/how-to-map-a-many-to-one-relationship-with-multiple-target-entities-with-jpa-and-hibernate/1761/6 "2018-11-28T06:15:12Z")

</div>

Check out [these examples](https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/test/java/org/hibernate/userguide/associations/any) from the Hibernate ORM GitHub repository. They work just fine and you can compare yours with these and spot the error.
