JPA 2.0-在父持久化上自动持久化子实体,给出org.hibernate.id.IdentifierGenerationException

JPA 2.0-在父持久化上自动持久化子实体,给出org.hibernate.id.IdentifierGenerationException,hibernate,jpa-2.0,Hibernate,Jpa 2.0,我有两个实体名为客户和他的Biiling地址。这种关系是一对一的。每个客户只有一个帐单地址。 我想在保留客户时自动保留账单地址。 客户id是客户实体的主键,也是地址实体中的主键和外键 //parent table public class CustomerDTO implements Serializable { @Id @GeneratedValue @Column(name = "customer_id") private Integer id; @OneToOne(fetch=Fetc

我有两个实体名为客户和他的Biiling地址。这种关系是一对一的。每个客户只有一个帐单地址。 我想在保留客户时自动保留账单地址。 客户id是客户实体的主键,也是地址实体中的主键和外键

//parent table
public class CustomerDTO implements Serializable {

@Id
@GeneratedValue
@Column(name = "customer_id")
private Integer id;

@OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL )
@PrimaryKeyJoinColumn(name="customer_id")
BillingAddressDTO billingAddressDTO;



//child table
public class BillingAddressDTO implements Serializable {
@Id
@Column(name="customer_id")
private Integer id;
这是我用来持久化实体的代码

    customerDTO = new CustomerDTO();
    customerDTO.setFirstName(firstName);

    billingAddressDTO = new BillingAddressDTO();
    billingAddressDTO.setBillingAddress(address1);
    customerDTO.setBillingAddressDTO(billingAddressDTO);
   //persisting customer entity
   customerDAO.persist(customerDTO);
我得到了以下例外

  Caused by: org.hibernate.id.IdentifierGenerationException: ids for this   
  class must be manually assigned before calling save():

我想给地址表分配相同的客户id,所以我不想手动分配。谢谢您的时间。

您需要的是所谓的派生标识符。在这种方法中,
CustomerDTO
(父实体)的主键与
BillingAddressDTO
(从属实体)共享

在上述场景中,父实体
CustomerDTO
具有简单的主键
customer\u id
,从属实体
BillingAddressDTO
共享由关系属性
CustomerDTO
映射的单个主键属性


更新:基于阿里评论的替代解决方案,以避免双向关系

@Entity
public class CustomerDTO implements Serializable {
    @Id
    private Integer id;

    @MapsId
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id")
    private BillingAddressDTO billingAddressDTO;
    ...
}
在上述场景中,父实体
BillingAddressDTO
具有简单的主键
customer\u id
,从属实体
CustomerDTO
共享由关系属性
BillingAddressDTO
映射的单个主键属性


从基础数据库的角度来看,实体将如下所示:

customer\u id firstname
-----------  ---------
1阿里巴巴
客户id账单地址
-----------  --------------
1我的地址
参考资料:

  • JPA 2.0规范,第2.4.1章:与派生身份对应的主键

谢谢@wypeprz。这对我来说很有效,但我有一个问题,如果我在这里犯了概念错误,请纠正我。将客户(父实体)放在地址(子实体)中不是一种逻辑冲突吗。我认为,这种关系是双向的,但我们不需要把客户放在地址中,因为无论何时我需要地址,我都可以从客户那里得到。我不会说这是一个错误,但实际上,这在概念上可能不适合您的需要。我已经更新了我的答案,以避免双向关系,这样你们就可以从客户那个里得到地址,而地址本身并不知道它属于谁。
@Entity
public class BillingAddressDTO implements Serializable {
    @Id
    private Integer id; // @Column is NOT allowed since id is indicated by @MapsId

    @MapsId
    @OneToOne(mappedBy = "billingAddressDTO")
    @JoinColumn(name = "customer_id")
    private CustomerDTO customerDTO;
    ...
}
@Entity
public class CustomerDTO implements Serializable {
    @Id
    private Integer id;

    @MapsId
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id")
    private BillingAddressDTO billingAddressDTO;
    ...
}
@Entity
public class BillingAddressDTO implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "customer_id")
    private Integer id;
    ...
}