英文:
Hibernate JPA Mapping Multiple Entities of the Same Type
问题
Address Entity
@Data
@NoArgsConstructor
@Entity(name = "address")
public class AddressEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private CustomerEntity customer;
}
Customer Entity
@Data
@NoArgsConstructor
@Entity(name = "customer")
public class CustomerEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne
private AddressEntity shippingAddress;
@OneToOne
private AddressEntity billingAddress;
}
英文:
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
@Data
@NoArgsConstructor
@Entity(name = "address")
public class AddressEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@?
private CustomerEntity customer;
}
Customer Entity
@Data
@NoArgsConstructor
@Entity(name = "customer")
public class CustomerEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@?
private AddressEntity shippingAddress;
@?
private AddressEntity billingAddress;
}
答案1
得分: 1
对于您的确切情况,我认为您可以使用@PostLoad。步骤如下:
- 使用
@OneToMany
注释将地址加载到集合中 - 使用@Transient注释
shippingAddress
和billingAddress
两个字段 - 创建一个用
@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
andbillingAddress
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
对于一个地址可能属于不同客户的情况:
@Entity
public class AddressEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
@Entity
public class CustomerEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private AddressEntity shippingAddress;
@ManyToOne
private AddressEntity billingAddress;
}
如果每个客户有唯一的地址,最好将地址存储在同一客户记录中。
你可以创建名为 `EmbeddedAddress` 的类,并使用 `@Embedded` 和 `@Embeddable` 注解。```
<details>
<summary>英文:</summary>
For the case when an address can belong different customers.
@Entity
public class AddressEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
@Entity
public class CustomerEntity
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private AddressEntity shippingAddress;
@ManyToOne
private AddressEntity billingAddress;
}
if each customer has unique address, better to store the addresses in the same customer record.
You can create class `EmbeddedAddress` and use `@Embedded` and `@Embeddable` annotations.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论