I have two simple entities
//Address @Entity
@OneToOne(fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "user_id", nullable = false)
private User user;
and
//User @Entity
@OneToOne(mappedBy = "user", orphanRemoval = true)
Address address;
But I am unable to update the user with a new address.
First approach:
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
addressRepository.save(address);
the code runs fine but an insert statement is done and now I have two address records in the database which causes future exceptions.
Second approach
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
user.setAddress(address); //added this line
addressRepository.save(address);
Now it throws exception
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Third approach
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
user.setAddress(address);
userRepository.save(user); //added this
addressRepository.save(address);
New exception:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
Temp solution
This solution works, but it's the most ugly code I've written and also I have no idea why it works. If someone has a better answer I will mark as solution.
First add cascade to the entity
@OneToOne(mappedBy = "user", orphanRemoval = true, cascade = CascadeType.ALL)
Address address;
And then update using this:
User user = userRepository.findByUsername("someemail");
if (user.getAddress() != null) {
addressRepository.delete(user.getAddress());
user.setAddress(address);
address.setUser(user);
userRepository.save(user);
} else {
address.setUser(user);
addressRepository.save(address);
}