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

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

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注释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


对于一个地址可能属于不同客户的情况:

@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>



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:

确定