Spring Data JPA - create @Composite key for the three tables

坚强是说给别人听的谎言 提交于 2019-11-30 10:39:23

Well, I know what you said, but I don't think it's what you meant. You said

Actually I've three tables, Stock, Category and Product. @ManyToMany relationship between Stock and Category, as well as @ManyToMany relationship between Category and Product.

It helps to think about this abstractly. In Chen notation what you said is

However this is probably not what you meant. This is problematic because you will need a new Category entity for every Stock and Product relationship. So, if you have a category of ETF then it will be duplicated for every stock in BobsBestETFs product, in fact for every instantiated relation.

What you meant is probably more along the lines of a Stock and Product relationship with a Category attribute, like so.

This this allows for many products each with many stocks and a specific category attribute for each product/stock relation. The issue you will have with this is that you don't want Category to be an attribute but rather a lookup table of categories, like so:

And I think this is what you are looking for. This should be fairly simple to implement with a composite ID but the examples you are showing seem to be somewhat out of date or unclear. Better to find better examples. This is how I would model the last schema.

@Entity
public class Stock {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}
@Entity
@Data
public class Product {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}
@Entity
public class Category {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}
@Entity
@Data
public class StockProduct {
    @EmbeddedId
    private StockProductPk id;

    @ManyToOne
    @MapsId("productId")
    private Product product;
    @ManyToOne
    @MapsId("stockId")
    private Stock stock;

    @ManyToOne
    private Category category;
}
@Embeddable
@Data
public class StockProductPk implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long stockId;
    private Long productId;
}

And as an example to use it:

private void create() {
    Category catEtf = new Category();
    categoryRepo.save(catEtf);
    Stock s1 = new Stock();
    stockRepo.save(s1);
    Product bobEtfs = new Product();
    productRepo.save(bobEtfs);

    // create a relationship
    StockProduct bs1 = new StockProduct();
    bs1.setId(new StockProductPk());
    bs1.setProduct(bobEtfs);
    bs1.setStock(s1);
    bs1.setCategory(catEtf);
    stockProductRepo.save(bs1); 
}
private void read() {
    StockProduct sp1 = new StockProduct();
    Product p1 = new Product();
    p1.setId(1L);
    sp1.setProduct(p1);
    List<StockProduct> bobEtfs = stockProductRepo.findAll(Example.of(sp1, ExampleMatcher.matching()));
    System.out.println(bobEtfs);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!