Reputation: 1773
I'm using Spring with Hibernate and I'm getting this exception. Here is what I'm trying to get: I have User and UserSettings classes, they're bounded with OneToMany and ManyToOne annotations like this:
public class UserImpl implements User, Serializable {
...some fields
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
private Set<UserSettingsImpl> settings;
}
public class UserSettingsImpl implements UserSettings, Serializable {
...some fields
@ManyToOne(cascade = CascadeType.ALL)
private UserImpl user;
}
Now, I want to add settings for user, that's how I'm doing it:
public long addSettings(final UserSettings settings) {
userSettingsDAO.persist((UserSettingsImpl) settings);
UserSettingsImpl settingsImpl = (UserSettingsImpl) settings;
User user = settings.getUser();
Set<UserSettingsImpl> settingsSet = (Set<UserSettingsImpl>) user.getSettingsSet();
settingsSet.add(settingsImpl);
userManager.updateUser(user); //it's just entityManager.merge(user);
return ((UserSettingsImpl) settings).getId();
}
And here comes the problem: User from UserSettings holds set with old settings and the new one (the settings, that I've just created and want to add), but old settings holds sets with user, that don't have new settings in it. That's why I'm getting the exception, I suppose, but I don't know how to fix it. (I think I'm working with Hibernate in the wrong way)
Upvotes: 1
Views: 369
Reputation: 2053
You will get old Usersettings
in the user
object with the current setup.
It is because, the way the merge
method works.
The way it works is it will create a copy of the object and then persist
and refresh
the object and return it back. So, in essense, the user
object which you do pass in to the userManager
will not be updated, but you have to get the returning value for the updated user
Upvotes: 1
Reputation: 10991
I would try something like below, the userImpl is referenced by the relationship from UserSettingsImpl, if you persist UserSettingsImpl, the operation is applied to the UserImpl because of the cascade, and if UserImpl is new it will be persisted otherwise nothing happens.
public long saveSettings(final UserSettings settings) {
userSettingsDAO.persist((UserSettingsImpl) settings);
return ((UserSettingsImpl) settings).getId();
}
and manage the bidirectional relationship in the class UserImpl:
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
private Set<UserSettingsImpl> settings = new HashSet<UserSettingsImpl>();
public void addUserSettings(UserSettings userSettings) {
this.settings.add(userSettings);
userSettings.setUserImpl(this);
}
Upvotes: 0