Reputation: 8033
I'm using hibernate in my spring mvc application and have a question about cascade. I see to many similar questions about it, but none of them can answer my question. Suppose I have User
and UserPosition
objects. User
has a collection of UserPosition
and also has one UserPosition
as the default position. Structure is look like this:
User:
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Collection<UserPosition> userPositionCollection;
public Collection<UserPosition> getUserPositionCollection() {
return userPositionCollection;
}
public void setUserPositionCollection(Collection<UserPosition> collection) {
this.userPositionCollection = collection;
}
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "default_User_Position_ID", referencedColumnName = "id")
private UserPosition defaultUserPosition;
public UserPosition getDefaultUserPosition() {
return defaultUserPosition;
}
public void setDefaultUserPosition(UserPosition defaultUserPosition) {
this.defaultUserPosition = defaultUserPosition;
}
UserPosition:
@JoinColumn(name = "user_id", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@OneToOne(fetch = FetchType.LAZY, mappedBy = "defaultUserPosition", cascade = CascadeType.PERSIST)
private User defaultUserPosition;
public User getDefaultUserPosition() {
return defaultUserPosition;
}
public void setDefaultUserPosition(User defaultUserPosition) {
this.defaultUserPosition = defaultUserPosition;
}
Now, my question is what's the best practice to use cascade for saving related objects?. In fact, I confused with these three solutions:
Solution 1:
User user = new User();
//some setters and getters
UserPosition userPosition = new UserPosition();
//some setters and getters
List<UserPosition> positionList = new ArrayList<>();
positionList.add(userPosition);
user.setDefaultUserPosition(userPosition);
user.setUserPositionCollection((Collection<UserPosition>) positionList );
session.persist(user)
Solution 2:
User user = new User();
//some setters and getters
UserPosition userPosition = new UserPosition();
//some setters and getters
userPosition.setUser(user);
userPosition.setDefaultUserPosition(user);
session.persist(userPosition)
Solution 3(Combination of two previous solutions):
User user = new User();
//some setters and getters
UserPosition userPosition = new UserPosition();
//some setters and getters
List<UserPosition> positionList = new ArrayList<>();
positionList.add(userPosition);
user.setDefaultUserPosition(userPosition);
user.setUserPositionCollection((Collection<UserPosition>) positionList );
userPosition.setUser(user);
userPosition.setDefaultUserPosition(user);
session.persist(user);
This is very important for me, so please help me. Which solution is correct and where should be cascade
property? Thank you for your time.
Upvotes: 5
Views: 2222
Reputation: 153690
The User
is the parent entity and cascading always propagates from Parent to Child entities.
Therefore, the User associations become:
@OneToMany(mappedBy = "user",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
orphanRemoval = true)
private Collection<UserPosition> userPositionCollection;
but for the default position, the User becomes the Child
of the association:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "default_User_Position_ID", referencedColumnName = "id")
private UserPosition defaultUserPosition;
In the UserPosition
class is the other way around:
@JoinColumn(name = "user_id", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private User user;
and
@OneToOne(fetch = FetchType.LAZY,
mappedBy = "defaultUserPosition",
cascade = CascadeType.PERSIST)
private User defaultUserPosition;
Then you also have to add the following utility methods that always synchronize both sides. These go into the User
class:
public void addUserPosition(UserPosition userPosition) {
userPositionCollection.add(userPosition);
userPosition.setUser(this);
}
public void addDefaultUserPosition(UserPosition userPosition) {
defaultUserPosition = userPosition;
userPosition.setDefaultUserPosition(this);
}
The persisting logic becomes:
User user = new User();
//some setters and getters
UserPosition userPosition = new UserPosition();
//some setters and getters
user.addUserPosition(userPosition);
user.setDefaultUserPosition(userPosition);
session.persist(user);
Upvotes: 3