akuma8
akuma8

Reputation: 4691

Bidirectional @OneToOne cascade issue JPA/Hibernate/Spring-Data

I have the entities bellow:

@Entity
public class User implements Serializable {

   private String username;

   @OneToOne( optional = false, mappedBy = "user", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL )
   private BankAccount bankAccount;
   //.....
}

And:

@Entity
public class BankAccount implements Serializable {

    @OneToOne( optional = false, fetch = FetchType.LAZY )
    @JoinColumn( name = "user", unique = true, referencedColumnName = "username" )
    private User user;
    //...
}

For me, I hope I'm right, User entity is the parent so I can cascade its operations to BankAccount. But when I try this :

User user = new User();
user.setBankAccount(new BanckAccount());
userRepository.save(user);

I have this exception :

org.hibernate.PropertyValueException: not-null property references a null or transient value : org.company.models.User.bankAccount

The save cascading is not propagated and I have to save bankAccount before setting it to the user. Am I missing something, should I review my association? Thanks

Upvotes: 2

Views: 5111

Answers (3)

akuma8
akuma8

Reputation: 4691

To complete this post, the cascade operation from child to parent works in this case @OneToOne(optional=false,mappedBy=...). If we set optional=false in the child side, cascading seems to work (at least Cascade.PERSIST).

Upvotes: 0

Kaushal28
Kaushal28

Reputation: 5557

Your mappedBy should be in child entity, which you want to be saved first. So here mapped by should be in BankAccount. Also You should use @JoinColumn in parent entity, so the foreign key of child can be stored in parent table. For example:

@Entity
public class User implements Serializable {

   private String username;

   @OneToOne( optional = false, orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL )
   @JoinColumn(name = "bank_account_id")
   private BankAccount bankAccount;
   //.....
}

And in BankAccount:

@Entity
public class BankAccount implements Serializable {

    @OneToOne( optional = false, fetch = FetchType.LAZY, mappedBy = "bankAccount")
    private User user;
    //...
}

See the similar example here.

Upvotes: 2

ewramner
ewramner

Reputation: 6233

You specify mappedBy on the wrong side of the relation. It should be specified on the inverse (non-owning) side. As you want the user to save the account the user must be the owner.

Upvotes: 4

Related Questions