0

I have a table (product) as follows which holds product related data

@Entity
@Table(name = "product")
public class ProductEntity {

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

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

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

// getters and setter
}

Among some of the products, there are some products which are derived from another product and there is requirement to store this mapping in a table (sub_product_mapping)

@Entity
@Table(name = "sub_product_mapping")
public class SubProductMappingEntity {

    @EmbeddedId
    private SubProductMappingKeyEntity subProductMappingKeyEntity;

    @MapsId("majorProductId")
    @ManyToOne
    @JoinColumn(name = "major_product_id", referencedColumnName = "id", nullable = false)
    private ProductEntity majorProduct;

    @MapsId("subProductId")
    @ManyToOne
    @JoinColumn(name = "sub_product_id", referencedColumnName = "id", nullable = false)
    private ProductEntity subProduct;

// getters and setter

and the key entity is as follows

@Embeddable
public class SubProductMappingKeyEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "major_product_id", nullable = false)
    private int majorProductId;
    @Column(name = "sub_product_id", nullable = false)
    private int subProductId;

// getters and setters

For a minor product there can only be one major product. But for a major product there can be multiple minor products. Since both the majorProduct and subProduct are instances of ProductEntity, what should be the relationship that should be used? Is it valid to have the relationships as follows?

 @MapsId("majorProductId")
    @ManyToOne
    @JoinColumn(name = "major_product_id", referencedColumnName = "id", nullable = false)
    private ProductEntity majorProduct;

    @MapsId("subProductId")
    @OneToOne
    @JoinColumn(name = "sub_product_id", referencedColumnName = "id", nullable = false)
    private ProductEntity subProduct;

(note: I am using Hibernate as the JPA implementation)

4
  • 2
    Since as you say “a minor product there can only be one major product”, is there any reason this wouldn’t be a simple self-referential hierarchy ( no need for another table) ? Take a look at stackoverflow.com/a/29975953/681444 Commented Sep 18 at 10:29
  • By the way, recommend not having the “Entity” suffix on all your class names (unless you really want to, of course). just calling your class “Product” (rather than “ProductEntity”) Is fine as standard practice. Commented Sep 18 at 10:56
  • There's nothing wrong with your design, as long as you need this mapping table. As mentioned, it could also be simple self-reference, as usually in classical parent-children scenario. Commented Sep 18 at 13:35
  • Even if you insist on having a separate relationship table, is there a genuine need to model it as an entity in its own right? (Not every table associated with a persistence unit has to have a corresponding entity class.) Commented Sep 18 at 13:39

1 Answer 1

0

For a minor product there can only be one major product. But for a major product there can be multiple minor products. Since both the majorProduct and subProduct are instances of ProductEntity, what should be the relationship that should be used?

That the two relationships are with the same entity type has no direct bearing on the cardinalities needed or allowed for those relationships. Each relationship is mapped independently of the others.

Is it valid to have the relationships [defined on SubProductMappingKeyEntity] as follows?

[one ManyToOne and one OneToOne, both with ProductEntity on the other end]

Yes, it is valid. However, if subproduct mappings don't have any of their own (mapped) properties, as shown in the question, then modeling them as their own entity is needlessly complicated. I would just map the relationship as a self-referential one directly on ProductEntity:

@Entity
@Table(name = "product")
public class ProductEntity {

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

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

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

    @ManyToOne(optional = true)
    ProductEntity majorProduct;
    // ...
}

And you can make that bidirectional if you like, by also adding

    @OneToMany(mappedBy = "majorProduct")
    List<ProductEntity> subProducts;
    // ...

You can back that with a relationship table such as you propose in the question, without creating an entity class for the relationship. You can also back it simply with a foreign key on the product table, referencing product itself.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.