Contornando o temido [org.hibernate.mapping.Column(authorities)]
Algo muito comum quando estamos configurando o Spring Security em nossos projetos é poder recebera temida mensagem de: org.hibernate.MappingException: Could not determine type for: java.util.Collection,geralmente ela aparece na etapa em que começamos a manipular nossa classe de Usuário do domínio, quandoimplementados a interface UserDetails o método getAuthorities necesita ser mapeado com a cardinalidade da sua escolha, porém mapear diretamente no método get pode confundir a implementação da JPA, no nosso caso o Hibernate, sendo assim, a solução é mapear a classe de domínio do usuário e a de perfil nos atributos, segue o exemplo:
package com.model; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Entity public class UserEntity implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String cpf; @Column(length = 10) private String password; @ManyToOne(cascade = CascadeType.ALL) private UserPhotoEntity userPhotoEntity; @CreationTimestamp private LocalDateTime createdAt; @UpdateTimestamp private LocalDateTime updatedAt; @ManyToMany(fetch = FetchType.EAGER) private List profileList = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public LocalDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } public LocalDateTime getUpdatedAt() { return updatedAt; } public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } public UserPhotoEntity getUserPhotoEntity() { return userPhotoEntity; } public void setUserPhotoEntity(UserPhotoEntity userPhotoEntity) { this.userPhotoEntity = userPhotoEntity; } @Override public Collection extends GrantedAuthority> getAuthorities() { return profileList; } public String getPassword() { return password; } @Override public String getUsername() { return null; } @Override public boolean isAccountNonExpired() { return false; } @Override public boolean isAccountNonLocked() { return false; } @Override public boolean isCredentialsNonExpired() { return false; } @Override public boolean isEnabled() { return false; } public void setPassword(String password) { this.password = password; } }
package com.model; import org.springframework.security.core.GrantedAuthority; import javax.persistence.*; @Entity public class Profile implements GrantedAuthority { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public String getAuthority() { return this.name; } }
Anotando apenas pelos atributos em ambos resolverá o problema, até a próxima!