简体   繁体   中英

How does Hibernate work with @OneToOne and Cascade.ALL? (using Spring)

I have a class Customer that has a OneToOne bidirectional relationship with a Subscription:

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

Now, when I create a customer with a subscription and call persist on the customer, it nicely saves the subscription as well into the database. However when I have already persisted a customer, and want to add a subscription, it fails with the following error:

Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [com.qmino.miredot.portal.domain.Subscription.customer]

I've written a test in order to explain what I want to achieve:

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

Where did I go wrong?

Cascade here is not the problem, Cascade indicates the action to be done by entity when deleted or updated. What is correct if you want to save complete entity. But for that, you need to have the correct data, your message suggest it tries to update the Customer entity but it founds an empty AccountDetails , so in order to correctly fetch the other entities, you need to add FecthType.EAGER , to get all attributes of mapped entities.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM