5

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.

1
  • How are user positions created and used usually? This is important, because the cascade property should be seen as part of the service layer and not as part of the how do I map something. Commented May 12, 2015 at 8:25

1 Answer 1

3

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);
Sign up to request clarification or add additional context in comments.

2 Comments

Where should I put cascade property in ManyToMany relationships? In which side of relation?
Check my first link on this answer. You are better using two onetomany instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.