I am trying to make a login with a ManyToMany, Hibernate connection. But at the time of loading the user by name, the collection of the (Set) roles first gets successfully, and then just as successfully deletes and, completing the session, goes into the sunset, leaving me with nothing. (Spring 4, Hibernate 5, Spring Security 4)

Here is the organization of entities:

@Entity @Table(name = "user") public class User { private Integer id; private String username; private String password; private boolean enabled = true; private Set<Role> roles = new HashSet<Role>(); //Getters & Setters @Id @GeneratedValue @Column(name = "id") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @NotEmpty @Column(name = "username", unique = true, nullable = false) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @NotEmpty @Column(name = "password", nullable = false) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Column(name = "enabled") public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> userRoles) { this.roles = roles; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + username.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof User)) return false; User other = (User) obj; if (username == null) { if (other.username != null) return false; } else if (!username.equals(other.username)) return false; return true; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", enabled=" + enabled + ", roles=" + roles + '}'; }} 

Class Role and RoleEnum:

 @Entity @Table(name = "role") public class Role { private Integer id; private String role = RolesEnum.USER.getUserRole(); //Getters & Setters @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getId() { return id; } public void setId(Integer userId) { this.id = userId; } @Column(name = "role") public String getRole() { return role; } public void setRole(String role) { this.role = role; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + role.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Role)) return false; Role other = (Role) obj; if (role == null) { if (other.role != null) return false; } else if (!role.equals(other.role)) return false; return true; } @Override public String toString() { return "Role{" + "id=" + id + ", role='" + role + '\'' + '}'; }} public enum RolesEnum { USER("USER"), ADMIN("ADMIN"); String userRole; private RolesEnum(String userRole) { this.userRole = userRole; } public String getUserRole() { return userRole; }} 

The tables are filled in the database: Bd

CustomUserDetailsService:

 @Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserService userService; @Transactional public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { com.alice.domain.User user = userService.findByUsername(username); if(user==null){ System.out.println("User not found"); throw new UsernameNotFoundException("Username not found"); } System.out.println("User for login : "+ user.getUsername()); List<GrantedAuthority> authorityList = buildUserAuthority(user.getRoles()); return buildUserForAuthentification(user, authorityList); } private User buildUserForAuthentification(com.alice.domain.User user, List<GrantedAuthority> authorityList){ boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; return new User(user.getUsername(),user.getPassword(),user.isEnabled(), accountNonExpired ,credentialsNonExpired, accountNonLocked, authorityList); } private List<GrantedAuthority> buildUserAuthority(Set<Role> userRoles){ Set<GrantedAuthority> authoritySet = new HashSet<GrantedAuthority>(); System.out.println("Уровень выборки"); for(Role userRole: userRoles){ authoritySet.add(new SimpleGrantedAuthority("ROLE_"+ userRole.getRole())); System.out.println("His role : "+ userRole); } return new ArrayList<GrantedAuthority>(authoritySet); }} 

Search by name tao:

  @SuppressWarnings("unchecked") public User findByUsername(String username) { User user = getByName("from User where username=?", username); System.out.println("behold... "+ user.getUsername()); return user;} //Реализация в общем дао @SuppressWarnings("unchecked") T getByName(String query, String name){ return (T) getSession().createQuery(query).setParameter(0, name).uniqueResult();} 

Logs from the console:

  16:26:26.345 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.alice.domain.User#1] 16:26:26.384 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving associations for [com.alice.domain.User#1] 16:26:26.425 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [com.alice.domain.User#1] 16:26:26.431 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer - Loading collection: [com.alice.domain.User.roles#1] 16:26:26.431 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - select roles0_.user_id as user_id1_9_0_, roles0_.role_id as role_id2_9_0_, role1_.id as id1_6_1_, role1_.role as role2_6_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=? Hibernate: select roles0_.user_id as user_id1_9_0_, roles0_.role_id as role_id2_9_0_, role1_.id as id1_6_1_, role1_.role as role2_6_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=? 16:26:26.437 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - Preparing collection intializer : [com.alice.domain.User.roles#1] 16:26:26.447 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - Starting ResultSet row #0 16:26:26.449 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.plan.exec.process.internal .CollectionReferenceInitializerI mpl - Found row of collection: [com.alice.domain.User.roles#1] 16:26:26.452 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving associations for [com.alice.domain.Role#1] 16:26:26.452 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [com.alice.domain.Role#1] 16:26:26.452 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext - 1 collections were found in result set for role: com.alice.domain.User.roles 16:26:26.453 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext - Collection fully initialized: [com.alice.domain.User.roles#1] 16:26:26.453 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.loading.internal.CollectionLoadContext - 1 collections initialized for role: com.alice.domain.User.roles 16:26:26.453 [http-nio-8080-exec-1] DEBUG org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered 16:26:26.453 [http-nio-8080-exec-1] DEBUG org.hibernate.loader.collection.plan .AbstractLoadPlanBasedCollectionInitializer- Done loading collection behold... lis User for login : lis Уровень выборки 16:26:26.456 [http-nio-8080-exec-1] DEBUG org.springframework.orm.hibernate5.HibernateTransactionManager - Initiating transaction commit 16:26:26.456 [http-nio-8080-exec-1] DEBUG org.springframework.orm.hibernate5.HibernateTransactionManager - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys= [EntityKey[com.alice.domain.User#1], EntityKey[com.alice.domain.Role#1]],collectionKeys= [CollectionKey[com.alice.domain.User.dictionarySet#1], CollectionKey[com.alice.domain.User.roles#1], CollectionKey[com.alice.domain.User.wordList#1]]]; ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] 16:26:26.456 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing 16:26:26.458 [http-nio-8080-exec-1] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades 16:26:26.463 [http-nio-8080-exec-1] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Dirty checking collections 16:26:26.477 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.Collections - Collection found: [com.alice.domain.User.dictionarySet#1], was: [com.alice.domain.User.dictionarySet#1] (uninitialized) 16:26:26.477 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.Collections - Collection found: [com.alice.domain.User.roles#1], was: [<unreferenced>] (initialized) 16:26:26.477 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.Collections - Collection found: [com.alice.domain.User.wordList#1], was: [com.alice.domain.User.wordList#1] (uninitialized) 16:26:26.477 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.internal.Collections - Collection dereferenced: [com.alice.domain.User.roles#1] 16:26:26.478 [http-nio-8080-exec-1] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 0 insertions, 1 updates, 0 deletions to 2 objects 16:26:26.478 [http-nio-8080-exec-1] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Flushed: 1 (re)creations, 0 updates, 1 removals to 4 collections 16:26:26.480 [http-nio-8080-exec-1] DEBUG org.hibernate.internal.util.EntityPrinter - Listing entities: 16:26:26.481 [http-nio-8080-exec-1] DEBUG org.hibernate.internal.util.EntityPrinter - com.alice.domain.User {password=$2a$10$Uch5QgeIMkDgHhMH0re9MutqV/tGYxl6XgSYpQRk.C1JG0xJIpCuG, wordList=<uninitialized>, dictionarySet=<uninitialized>, roles=[], telephone=333444, id=1, creation_date=2017-05-14 00:00:00.0, email=mimi@gi.com, enabled=true, username=lis} 16:26:26.481 [http-nio-8080-exec-1] DEBUG org.hibernate.internal.util.EntityPrinter - com.alice.domain.Role{role=ADMIN, id=1} 16:26:26.525 [http-nio-8080-exec-1] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister - Deleting collection: [com.alice.domain.User.roles#1] 16:26:26.537 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - delete from user_role where user_id=? Hibernate: delete from user_role where user_id=? 16:26:26.538 [http-nio-8080-exec-1] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister - Done deleting collection 16:26:26.538 [http-nio-8080-exec-1] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister - Inserting collection: [com.alice.domain.User.roles#1] 16:26:26.538 [http-nio-8080-exec-1] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister - Collection was empty 16:26:26.546 [http-nio-8080-exec-1] DEBUG org.springframework.orm.hibernate5.HibernateTransactionManager - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys= [EntityKey[com.alice.domain.User#1], EntityKey[com.alice.domain.Role#1]],collectionKeys= [CollectionKey[com.alice.domain.User.dictionarySet#1], CollectionKey[com.alice.domain.User.wordList#1], CollectionKey[com.alice.domain.User.roles#1]]]; ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction 16:26:26.546 [http-nio-8080-exec-1] DEBUG org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch 16:26:26.651 [http-nio-8080-exec-1] DEBUG org.springframework.security.web .authentication.session.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web .authentication.session.ChangeSessionIdAuthentic ationStrategy@5369c6b8 

I tried to change the eager to lazy, but in no matter whether it is pulled up or not, it is still deleted. In equals () and hashcode () put the user name to check (will not change). There is a vague doubt that the snag is in them, because I use HashSet, but I don’t know where exactly. There were also suggestions that the problem may arise from the place of initialization of the set (is this real?). Help pliz thanks in advance =)

    1 answer 1

    It seems that somewhere the elements of the User.roles collection are User.roles , but I didn’t find it in the above code - probably, not all the source code accompanying the process is given in the question. Here are the log messages about this:

     Collection dereferenced: [com.alice.domain.User.roles#1] ... ...roles=[]... ... delete from user_role... 

    it looks like the roles collection of a User object is somewhere replaced entirely with an empty collection.

    • It seems to have led all the code in which the role is somehow involved. God knows, in any case, thank you very much, I will go on looking. - FoxsTail