Nullable @ManyToOne not accepting null value [duplicate]
Nullable @ManyToOne not accepting null value [duplicate]
This question already has an answer here:
I have a many-to-one relationship that I want to be nullable.
Here's the parent:
@Entity
@Table(name = "C_CUSTOMER")
class User
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
And the child:
@Entity
@Table(name = "C_PROFILE")
class Profile
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(optional = true)
@JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
When I try to save a profile without a userId, the following error is threw:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : fr.entity.Profile.user -> fr.entity.User
If the field userId has a value, then it works smoothly.
I tried a bunch of answers from other questions on SO, but so far nothing has worked. The easiest way would be to ditch the relation in the entity files and use Integer customerId, but that's not really satisfactory for me, 'cause it would mean that the cascade deletion wouldn't work anymore.
Integer customerId
Thanks in advance.
The problem comes from a entity <-> dto mapping. I added an answer about it, will probably edit if I come across a workaround.
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
Profile
Save the
User first before adding to your Profile entity. Please also make sure that when you're populating your User and Profile, that you're adding each entity into the other creating the bi-directional relationship.– Dan
Aug 23 at 12:34
User
Profile
User
Profile
The error is only when the
User is null, so I don't want to add it. I want the field to be null.– RoadEx
Aug 23 at 12:37
User
null
null
Are you really sure? Because Hibernate complaints that the user is unsaved!
– Simon Martinelli
Aug 23 at 12:48
Well, I've just end a new debug of it and... Turns out that the User field isn't null. Mea culpa - it was trying to add a
User with all the fields at null. Sooo... The question now is : shouldn't Userbe null ? Or i've missed something.– RoadEx
Aug 23 at 12:55
User
User
2 Answers
2
Tried your code on my machine. Below are my entity classes:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "C_PROFILE")
@Data
public class Profile
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@ManyToOne(optional = true)
@JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
User class:
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "C_CUSTOMER")
@Data
class User
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
@OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
Repository:
import org.springframework.data.jpa.repository.JpaRepository;
import io.polarisdev.returns.model.Profile;
public interface ProfileRepository extends JpaRepository<Profile, String>
Code to save the Profile without user:
Profile p = new Profile();
p.setName("Name");
profileRepository.save(p);
So, after some digging inside the generated files: there's no solution to it (for now). The problem comes from a mapping between entity <-> dto, using mapstruct: having not mentioned this step, no wonder it wasn't working like it should for me... Well, the profile mapper contains this:
protected User profileToUser(Profile profile)
if ( profile == null )
return null;
User user = new User();
User.setId(profile.getUserId());
return user;
Meaning I need to reassign a null value before saving the Profile. There is apparently a ticket about this on the github, so wait and see. Seems like there's some suggestions too to make it work, so if I come across one that work, i'll edit this answer (unless someone answer with a solution before).
Profile
EDIT
After a few researches on the mapstruct git and SO, I came across a solution that work, though it's not really elegant.
@AfterMapping
public Profile doAfterMapping(@MappingTarget Profile entity)
if (entity != null && entity.getUser().getId() == null)
entity.setUser(null);
return entity;
So... I'll put the question in duplicate. Thanks a bunch to the ones that helped me (though I wouldn't have need to post if I had been more vigilant).
can you please add the
Profilepojo in the question?– Leviand
Aug 23 at 12:33