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

时间:2015-03-04 16:37:34

标签: hibernate jpa-2.0

我有两个名为Customer的实体和他的Biiling地址。这种关系是一对一的。每个客户只有一个帐单地址。 我希望在客户持久时自动保留帐单邮寄地址。 客户ID是Customer实体的主键,它也是地址实体中的主键和外键。

//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分配给地址表,所以我不想手动分配它。谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

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

@Entity
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")
    private BillingAddressDTO billingAddressDTO;
    ...
}
@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;
    ...
}

在上面的场景中,父实体CustomerDTO有一个简单的主键customer_id,并且从属实体BillingAddressDTO共享由关系属性{{1}映射的单个主键属性。 }}


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

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; ... } 有一个简单的主键BillingAddressDTO,并且从属实体customer_id共享由关系属性{{1}映射的单个主键属性。 }}


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

CustomerDTO

参考文献:

  • JPA 2.0规范,第2.4.1章:与派生身份相对应的主要密钥