Java Hibernate如何与@OneToOne和Cascade.ALL一起工作?(使用弹簧)

Java Hibernate如何与@OneToOne和Cascade.ALL一起工作?(使用弹簧),java,hibernate,jpa,spring-data,one-to-one,Java,Hibernate,Jpa,Spring Data,One To One,我有一个与订阅具有OneTONE双向关系的类客户: @Entity @Table(name = "customers") public class Customer{ @OneToOne(mappedBy="customer",cascade = CascadeType.ALL) private Subscription currentSubscription; } @Entity @Table(name = "subscriptions") public class Subs

我有一个与订阅具有OneTONE双向关系的类客户:

@Entity
@Table(name = "customers")
public class Customer{
    @OneToOne(mappedBy="customer",cascade = CascadeType.ALL)
    private Subscription currentSubscription;
}

@Entity
@Table(name = "subscriptions")
public class Subscription {

    @Id
    @Column(columnDefinition = "INT8",name="id", unique=true, nullable=false)
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="customer"))
    private Long id;

    @OneToOne
    @PrimaryKeyJoinColumn
    private Customer customer;
}
现在,当我创建一个具有订阅的客户并对该客户调用persist时,它会很好地将订阅保存到数据库中。但是,当我已经持久化了一个客户,并且想要添加订阅时,它会失败,并出现以下错误:

原因:org.hibernate.id.IdentifierGenerationException:已尝试 从空的一对一属性分配id [com.qmino.miredot.portal.domain.Subscription.customer]

我写了一个测试来解释我想要达到的目标:

@Test
public void shouldCascadeUpdateSubscription(){
    Customer owner = customerRepository.save(CustomerMother.getCustomer(false));

    Subscription subscription = SubscriptionBuilder.create()
            .setBillingDayOfMonth(LocalDate.now().getDayOfMonth())
            .setSubscriptionPlan(subscriptionPlan)
            .build();

    subscription.setCustomer(owner);
    owner.setCurrentSubscription(subscription);

    customerRepository.save(owner);

    Customer result = customerRepository.findOne(owner.getId());
    assertThat(result.getCurrentSubscription(),is(notNullValue()));
    assertThat(result.getCurrentSubscription().getId(),is(result.getId()));
}

哪里出错了?

这里不是问题所在,Cascade表示实体在删除或更新时要执行的操作。如果要保存完整的实体,请选择正确的选项。但为此,您需要有正确的数据,您的消息建议它尝试更新
客户
实体,但它发现一个空的
帐户详细信息
,因此为了正确获取其他实体,您需要添加
FecthType.EAGER
,以获取映射实体的所有属性

@OneToOne(mappedBy="customer",cascade = CascadeType.ALL, fetch = FetchType.EAGER))

我应该澄清一下,我得到的错误发生在第二次保存所有者时。我只在测试接近尾声时得到了一个客户,问题发生在这之前。FetchType.EAGER的缺点是,您将对关系进行单独的select查询。有时可能会有问题。你说实体是双向链接的吗?看起来不像。您的订阅没有客户。所以“mappedBy=“customer”是多余的。我的坏客户犯了一个错误。现在应该是正确的。subscription.setAccountDetails(所有者);为什么不遵循EJB规范呢?Hibernate应该有一个合适的setter/getter。因此,不是“setAccoundDetails”应该是“setCustomer”/“getCustomer”,而是一个错误,我错误地键入了错误的类,并且忘记了setter。很抱歉。所以parameters=@Parameter(name=“property”,value=“accountDetails”也应该是客户?请修复所有输入错误