简体   繁体   中英

Hibernate doesn't update entity with either merge or update

I have User and UserRole class. I want to delete a role from User and update it.

this is my deleteRole method:

public void deleteRole(String username, String role) {
     User user = userDao.findByUserName(username);
            Set<UserRole> userRoles = user.getUserRole();
            for (UserRole tempRole: userRoles) {
                if (tempRole.getRole().equals(role)){
                    userRoles.remove(tempRole);
                }
            }
            user.setUserRole(userRoles);
      updateUser(user);
}

here is my updateUser method:

 public void update(User user) {
       sessionFactory.getCurrentSession().merge(user);
    }

I tried the update, merge, saveOrUpdate but nothing changes. I still have all the same roles.

user entity

@Entity
@Table(name = "USERS")
public class User {
    @Id
    @Column(name = "USERNAME", nullable = false, unique = true)
    private String username;

@Column(name = "PASSWORD", nullable = false)
private String password;

@Transient
private String confirmPassword;

@Column(name = "ENABLED", nullable = false)
private boolean enabled = true;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.EAGER)
private Set<UserRole> userRole = new HashSet<>();

here is the userRole entity

@Entity
@Table(name = "USER_ROLES", uniqueConstraints = @UniqueConstraint(
        columnNames = { "ROLE", "USERNAME" }))
public class UserRole {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "user_role_id",
            unique = true, nullable = false)
    private Integer userRoleId;

    @Column(name = "ROLE")
    private String role;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "USERNAME")
    private User user;

UPDATE When i remove role from user and merge it and then try to get userByUsername from base it shows that this user doesn't have this role, but when i try to open my html page with users it appears again in list.

Elaborating on my comment before - I think you've defined UserRole as the owner of the relationship (the one not annotated with the mappedBy attribute!), therefore setting the user at UserRole rather than setting UserRole at User might solve it. Try setting the user member for the required userRole rather than the other way around.

    public void deleteRole(String username, String role) {
    User user = userDao.findByUserName(username);
    Set<UserRole> userRoles = user.getUserRole();
    for (UserRole tempRole: userRoles) {
        if (tempRole.getRole().equals(role)){
            tempRole.setUser(null);
            sessionFactory.getCurrentSession().merge(tempRole);
        }
    }
}

I'll add an answer as I believe you are missing the gist of cascade.

You are looking for orphan removal. See https://www.baeldung.com/delete-with-hibernate

See also jpa removing item from list - the syntax differs between older versions of Hibernate and Jpa 2.0

Additionally, you are relying on jdbc auto-commit instead of making your methods @Transactional . Thus your entity is detached just after retrieving it with find. Then you re-attach your entity with merge. This makes no sense. On top of that, Hibernate uses dirty-checking, so you need no operations on Session to execute updates. They will be run when the session is flushed.

All of the above holds as long as you want to rely on cascade to remove your userRole. You may as well retrieve the one you are looking for, and use Session.remove with the UserRole. You will more like end up with bettr performing code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM