Search code examples
javaspringjpaspring-data-jpa

How to map a JPA entity field to different entity types based on a condition?


I have a JPA Entity "Food" with a field "idPtr" that I want to map to either a "Vegetable" Entity or a "Fruit" Entity depending on the value of the "code" field. Here's what I have so far:

@Getter
@Setter
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @Column(name = "ptr_id")
    private Integer idPtr;

    // ...
}

I want to modify the "idPtr" field to be either an Vegetable or a Fruit entity, depending on the value of the code field, in order to have something like this :

@Getter
@Setter
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ptr_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Vegetable ptrVegetable;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ptr_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Fruit ptrFruit;

    // ...
}

The condition would be something like if("VEG".equals(code)) then we would join this Food with the entity Vegetable


Solution

  • I think you can use Single Table inheritance strategy. In this case, Food entity should have two inheritors. The first one joins Vegetable and the second one joins Fruit. Look at the code example below.

    @Getter
    @Setter
    @Entity
    @Table(name = "food")
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name="code", 
      discriminatorType = DiscriminatorType.STRING)
    class Food {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "code")
        private String code;
    }
    
    
    @Entity
    @DiscriminatorValue("VEG")
    class VegetableFood extends Food {
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "ptr_id", referencedColumnName = "id", insertable = false, updatable = false)
        private Vegetable ptrVegetable;
    }
    
    @Entity
    @DiscriminatorValue("FRUIT")
    class FruitFood extends Food {
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "ptr_id", referencedColumnName = "id", insertable = false, updatable = false)
        private Fruit ptrFruit;
    }