【问题标题】:JPA Entity relationship?JPA 实体关系?
【发布时间】:2016-01-03 22:00:18
【问题描述】:

我拥有名为 Shop 的实体和不同类型的商店(运动、服装、科技......)。该类型列表可能是预定义的。一个商店可以有多种类型。最好的表达方式是什么?

我创建了两个实体 Shop 和 Type。

@Entity
@Table(name = "store")
public class Store {

  @GeneratedValue(strategy = GenerationType.AUTO)
  @Id
  private Long id;

  ...
}

@Entity
@Table(name = "type")
public class Type {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    private String name; //sport, clothes, tech...
}

我应该在这两个实体之间使用什么类型的关系?

【问题讨论】:

  • 为什么一个店铺可以有多种类型?您的意思是一家商店可以销售不同“类型”的产品吗?
  • @Snusmumrikken 是的,商店可以销售不同的产品,这就是为什么商店可以有多种类型。
  • 好吧,等一下。我不使用“类型”来捕捉您正在寻找的概念。我会写一个答案。
  • 为什么不键入枚举?
  • @NeilStockton 如果一个商店只能有一种类型,我会选择枚举,但我不确定 ManyToMany 与枚举的关系。也许我尝试像下面建议的答案之一一样使用 Type 作为枚举。

标签: java sql hibernate postgresql jpa


【解决方案1】:

鉴于您说Type 可能是预定义的,将其建模为enum 并利用ElementCollection 似乎更合理

(我不得不承认我没有尝试将它们结合使用,但我相信它应该可以工作:P)

public enum Type {
    SPORT, CLOTHES, TECH
}

public class Shop {
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(
        name="SHOP_TYPE",
        joinColumns=@JoinColumn(name="SHOP_ID")
    )
    @Column(name="TYPE")
    // mapping for enum by usertype or other way, depending on JPA version you are using
    private List<Type> types;
}

当然,如果您想对其进行更复杂的操作,您可以将SHOP_TYPE 建模为实体(例如ShopType),但在我看来,上述描述的领域模型更合理。


即使您不希望预定义Type(即您可以在应用程序中创建任何类型),将其建模为ManyToMany 关系仍然更合理:

public class Type {
    @Id
    @Column(name="TYPE_ID")
    private Long id

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

public class Shop {
    @Id
    @Column(name="SHOP_ID")
    private Long id;

    @ManyToMany
    @JoinTable( 
        name="SHOP_TYPE",
        joinColumns=@JoinColumn(name="SHOP_ID"),
        inverseJoinColumns=@JoinColumn(name="TYPE_ID"))
    private List<Type> types;
}

只需要注意一件事:拥有一个包含 String 作为类型名称的 Type 实体看起来不正确,并参考 Shop(正如一些答案所建议的那样)。 Type 应该是其自身的一个实体,例如,具有CLOTHES 类型的不同商店应该引用相同的CLOTHES 实体(除非您将类型视为某种任意标签)

【讨论】:

    【解决方案2】:

    StoreType 多对多关系与名为 STORE_TYPE_MAPS 的第三个 / 连接表链接。

    商店实体:

    @Entity
    @Table(name = "store")
    public class Store {
    
      @GeneratedValue(strategy = GenerationType.AUTO)
      @Id
      private Long id;
    
     @ManyToMany(fetch = FetchType.LAZY, targetEntity=Type.class)
     @JoinTable(name="STORE_TYPE_MAPS",         
     joinColumns=@JoinColumn(name="STORE_ID"),
     inverseJoinColumns=@JoinColumn(name="TYPE_ID")
     private Set<Type> types;
      //... getter-setter
    }
    

    【讨论】:

    • 您在此处拥有的 Type 在概念上与 OP 正在寻找的内容不一致,并且恕我直言,这种映射并没有提供合理的域模型。
    【解决方案3】:

    如果 Type 是一个实体,则将其设为ManyToMany

    @ManyToMany
    @JoinTable(name="Store_Type")
    private List<Type> types;
    

    也可以是enum

    【讨论】:

    • 如果您确定希望能够将多个“类型”分配给“商店”,这是最佳答案。如果您只想将单个“类型”分配给“商店”,则可以使用“多对一”关系。
    • 所以我决定使用联接表 Store_Type 来处理 Type 和 Store(或 Shop,我只是注意到我在问题中称它不同)之间的 @ManyToMany 关系。
    【解决方案4】:

    我更喜欢创建一个名为 ShopType 的新实体,ManyToMany 关系将如下所述创建。

    这个新实体允许您在连接表“ShopType”中有额外的列(这不能用简单的@ManyToMany 完成)。例如,您可以添加这样的信息:“每个商店中每种类型的商品数量”。

    代码如下:

    public class Shop {
        @Id
        @Column(name="SHOP_ID")
        private Long id;
    
        @OneToMany(mappedBy = "shop", cascade = CascadeType.ALL)
        private List<JoinAchatType> joinShopType = new ArrayList();
    }
    
    public class ShopType {
        @ManyToOne
        @JoinColumn(name = "SHOP_ID")
        private Shop shop;
    
        @ManyToOne
        @JoinColumn(name = "TYPE_ID")
        private Type type;
    
        private int numberArticle;
    }
    
    public class Type {
        @Id
        @Column(name="TYPE_ID")
        private Long id;
    
        @OneToMany(mappedBy = "type", cascade = CascadeType.ALL)
        private List<JoinAchatType> joinShopType = new ArrayList();
    }
    

    有关更多信息,请查看以下链接:

    【讨论】:

      猜你喜欢
      • 2013-06-01
      • 2012-06-23
      • 1970-01-01
      • 2021-05-22
      • 2013-04-25
      • 2011-02-14
      • 2021-05-25
      • 1970-01-01
      • 2021-12-21
      相关资源
      最近更新 更多