Hibernate如何与@OneToOne和Cascade.ALL一起使用? (使用Spring)

时间:2015-04-13 07:58:09

标签: java hibernate jpa spring-data one-to-one

我有一个Customer类,它具有与订阅的OneToOne双向关系:

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

现在,当我创建一个订阅客户并在客户上保持呼叫​​时,它可以很好地将订阅保存到数据库中。但是,当我已经保留了一个客户并希望添加订阅时,它会因以下错误而失败:

  

引起:org.hibernate.id.IdentifierGenerationException:尝试过   从null一对一属性中分配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()));
}

我哪里出错了?

1 个答案:

答案 0 :(得分:2)

此处级联不是问题,Cascade指示实体在删除或更新时要执行的操作。如果要保存完整的实体,这是正确的。但为此,您需要拥有正确的数据,您的消息建议它尝试更新Customer实体,但它发现空AccountDetails,因此为了正确获取其他实体,您需要添加FecthType.EAGER,以获取映射实体的所有属性。

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