ROZZ
ROZZ

Reputation: 1454

JPA (Hibernate) Map multiple entities to one common table (entity)

I'm having situation where I have multiple entities (Users, Products, Categories) where each of have one or more Images. I want to use only one Image table to persist the info about the images.

I like to achieve something like this with JPA (Hibernate):

id  foreign_key     image_type       file_path
1   1               PROFILE_USER     /file/….
2   2               PROFILE_USER     /file/….
3   3               CATEGORY_IMAGE   /file/….
4   4               CATEGORY_IMAGE   /file/….
5   1               PRODUCT_IMAGE    /file/….

Where foreign_key is the primary id key for the different entity types ( Users, Categories, Products etc..) The combination of foreign_key and image_type indicates for the specific entity ( PROFILE_USERS(Users), PRODUCT_IMAGE(Products), CATEGORY_IMAGE(Category) etc..

I want to do this because, it it not cool to have separate image table for the different cases ( Users - > users_images, Products -> product_images, Category -> category_images)

Upvotes: 1

Views: 1895

Answers (1)

ROZZ
ROZZ

Reputation: 1454

Maybe I was not able to explain it correctly. I managed to do it as I wanted with @Where annotation on each ProductImage, UserImage etc.. Let me explain it.

@Getter
@Setter
@Entity
@Table(name = "products")
@EntityListeners(AuditingEntityListener.class)
public class Product {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Long id;


  @OrderBy("id")
  @JoinColumn(name = "image_type_id")
  @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.EAGER, targetEntity = ProductImage.class)
  private Set<ProductImage> images = new LinkedHashSet<>();


}

--

@Table(name = "images")
@EntityListeners(AuditingEntityListener.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="image_type",
    discriminatorType = DiscriminatorType.STRING)
public class Image {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Long id;

  @Column(name = "original_file_name")
  private String originalFileName;

  @Column(name = "file_name")
  private String fileName;

  @Column(name = "file_path")
  private String filePath;

  @Column(name = "file_size")
  private Long fileSize;

  @Column(name = "thumbnail_path")
  private String thumbnailPath;

}

--

@Entity
@DiscriminatorValue("PRODUCT_IMAGE")
@Where(clause = "image_type = \"PRODUCT_IMAGE\"")
public class ProductImage extends Image {


}

Now we have one Image table which is distinguished by each implementation (ProductImages, UserImages etc) only by DiscriminatorColumn and image_type_id combination of each defines one specific instance from Product ( and his ProductImages). When the products and his images are query, my select statement is like this - "where ( images0_.image_type = "PRODUCT_IMAGE") and images0_.image_type_id=? order by images0_.id"

There is no need of JoinTable which should contain the relation for image id and product id, in order to distinguishes the images for specific product instance.

@Chris does this make sense for you? Can you find some Pros and Cons for this approach ?

Upvotes: 1

Related Questions