Hibernate JPA映射相同类型的多个实体

huangapple go评论122阅读模式
英文:

Hibernate JPA Mapping Multiple Entities of the Same Type

问题

Address Entity

  1. @Data
  2. @NoArgsConstructor
  3. @Entity(name = "address")
  4. public class AddressEntity
  5. {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.AUTO)
  8. private Long id;
  9. @ManyToOne
  10. private CustomerEntity customer;
  11. }

Customer Entity

  1. @Data
  2. @NoArgsConstructor
  3. @Entity(name = "customer")
  4. public class CustomerEntity
  5. {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.AUTO)
  8. private Long id;
  9. @OneToOne
  10. private AddressEntity shippingAddress;
  11. @OneToOne
  12. private AddressEntity billingAddress;
  13. }
英文:

I have a one-to-many relationship with Customer and Address, but I'm not sure how to represent this with JPA. I don't want use @OneToMany for the AddressEntity's in CustomerEntity because I want to avoid wrapping it in a Collection.

I'm wondering what annotation or even other strategies I can use to maintain the relationship where one customer will, for simplicity, always have two addresses. Any suggestions are appreciated!

Address Entity

  1. @Data
  2. @NoArgsConstructor
  3. @Entity(name = "address")
  4. public class AddressEntity
  5. {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.AUTO)
  8. private Long id;
  9. @?
  10. private CustomerEntity customer;
  11. }

Customer Entity

  1. @Data
  2. @NoArgsConstructor
  3. @Entity(name = "customer")
  4. public class CustomerEntity
  5. {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.AUTO)
  8. private Long id;
  9. @?
  10. private AddressEntity shippingAddress;
  11. @?
  12. private AddressEntity billingAddress;
  13. }

答案1

得分: 1

对于您的确切情况,我认为您可以使用@PostLoad。步骤如下:

  • 使用@OneToMany注释将地址加载到集合中
  • 使用@Transient注释shippingAddressbillingAddress两个字段
  • 创建一个用@PostLoad注释的公共方法
  • 初始化您的两个瞬态字段(您需要至少一个枚举来区分这两个地址)

为什么上述步骤会起作用?

  • PostLoad在从数据库加载实体后被调用
  • 这些字段需要是瞬态的,因为它们不映射到数据库列

可以在这里找到一个相关示例。

虽然上述方法可以解决您的问题,但它在您的JPA实体中增加了一定程度的冗余。我建议使用@OneToMany,并确保在AddressEntity中添加一个枚举来检查地址是用于运输还是用于账单。

另外,考虑到您提到客户和地址之间是一对多的关系,地址和客户之间是多对一的关系。在AddressEntity类中要使用的注释是@ManyToOne

英文:

For your exact scenario, I think you could go for @PostLoad.
The steps would be:

  • use @OneToMany annotation to load the addresses into a collection
  • annotate both shippingAddress and billingAddress with @Transient
  • create a public method annotated with @PostLoad
  • initialise your 2 transient fields (you need to have at least an enum to discriminate between the addresses)

Why would the steps above work?

  • PostLoad is invoked after an entity is loaded from the database
  • the fields need to be transient, because they are not mapped to database columns

A relevant example can be found here.

While the approach above would solve your problem, it adds some degree of verbosity in your JPA entities. I would suggest to go for @OneToMany and make sure you add an enum in AddressEntity to check if an address is for shipping or billing.

Also, given that you mentioned that there is a one-to-many relationship between a customer and an address, then there is a many-to-one relationship between an address and a customer. The annotation to use in the AddressEntity class is @ManyToOne

答案2

得分: 1

  1. 对于一个地址可能属于不同客户的情况:
  2. @Entity
  3. public class AddressEntity
  4. {
  5. @Id
  6. @GeneratedValue(strategy = GenerationType.AUTO)
  7. private Long id;
  8. }
  9. @Entity
  10. public class CustomerEntity
  11. {
  12. @Id
  13. @GeneratedValue(strategy = GenerationType.AUTO)
  14. private Long id;
  15. @ManyToOne
  16. private AddressEntity shippingAddress;
  17. @ManyToOne
  18. private AddressEntity billingAddress;
  19. }
  20. 如果每个客户有唯一的地址,最好将地址存储在同一客户记录中。
  21. 你可以创建名为 `EmbeddedAddress` 的类,并使用 `@Embedded` `@Embeddable` 注解。```
  22. <details>
  23. <summary>英文:</summary>
  24. For the case when an address can belong different customers.
  25. @Entity
  26. public class AddressEntity
  27. {
  28. @Id
  29. @GeneratedValue(strategy = GenerationType.AUTO)
  30. private Long id;
  31. }
  32. @Entity
  33. public class CustomerEntity
  34. {
  35. @Id
  36. @GeneratedValue(strategy = GenerationType.AUTO)
  37. private Long id;
  38. @ManyToOne
  39. private AddressEntity shippingAddress;
  40. @ManyToOne
  41. private AddressEntity billingAddress;
  42. }
  43. if each customer has unique address, better to store the addresses in the same customer record.
  44. You can create class `EmbeddedAddress` and use `@Embedded` and `@Embeddable` annotations.
  45. </details>

huangapple
  • 本文由 发表于 2020年7月31日 04:54:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63181257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定