У меня проблема с аутентификацией после сохранения дочернего класса в моей базе данных.
У меня есть три класса (Client, RetailClient и WholesaleClient), и я хочу зарегистрировать пользователя по типу.Когда я сохраняю строку как Клиент (родительский), все работает, но когда я хочу сохранить объект как дочерний (RetailClient, WholesaleClient), у меня возникает проблема с регистрацией (ошибка 401).Можно ли войти с наследованием?
Мой код:
Родитель
@Entity
@Table(name = "clients", uniqueConstraints = {
@UniqueConstraint(columnNames = {
"username"
}),
@UniqueConstraint(columnNames = {
"email"
})
})
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "Type",
discriminatorType = DiscriminatorType.STRING
)
public class Client extends DateAudit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max = 40)
private String name;
@NotBlank
@Size(max = 15)
private String username;
@NaturalId
@NotBlank
@Size(max = 40)
@Email
private String email;
@NotBlank
@Size(max = 100)
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
public Client() {
}
public Client(String name, String username, String email, String password) {
this.name = name;
this.username = username;
this.email = email;
this.password = password;
}
... getters and setters
Ребенок
@Entity
@DiscriminatorValue("RetailClient")
public class RetailClient extends Client {
@Column(name = "First_Name")
private String firstName;
@Column(name = "Second_Name")
private String secondName;
public RetailClient(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
... getters and setters
Контроллер с ошибкой 401:
RetailClient retailClient = new RetailClient("TestImie", "TestNazwisko");
retailClient.setName(signUpRequest.getName());
retailClient.setUsername(signUpRequest.getUsername());
retailClient.setEmail(signUpRequest.getEmail());
retailClient.setPassword(signUpRequest.getPassword());
retailClient.setPassword(passwordEncoder.encode(retailClient.getPassword()));
Role clientUserRole = roleRepository.findByName(RoleName.ROLE_USER)
.orElseThrow(() -> new AppException("User Role not set."));
retailClient.setRoles(Collections.singleton(clientUserRole));
Client result = clientRepository.save(retailClient);
Контроллер без ошибок:
Client client1 = new Client(signUpRequest.getName(), signUpRequest.getUsername(),
signUpRequest.getEmail(), signUpRequest.getPassword());
client1.setPassword(passwordEncoder.encode(client1.getPassword()));
Role userRole = roleRepository.findByName(RoleName.ROLE_USER)
.orElseThrow(() -> new AppException("User Role not set."));
client1.setRoles(Collections.singleton(userRole));
Client result = clientRepository.save(client1);
CustomUserDetailService:
@Service
public class CustomUserDetailsService implements UserDetailsService {
private ClientRepository clientRepository;
public CustomUserDetailsService(ClientRepository clientRepository) {
this.clientRepository = clientRepository;
}
@Override
@Transactional
public UserDetails loadUserByUsername(String usernameOrEmail)
throws UsernameNotFoundException {
Client client = clientRepository.findByUsernameOrEmail(usernameOrEmail, usernameOrEmail)
.orElseThrow(() ->
new UsernameNotFoundException("User not found with username or email : " + usernameOrEmail)
);
return UserPrincipal.create(client);
}
@Transactional
public UserDetails loadUserById(Long id) {
Client client = clientRepository.findById(id).orElseThrow(
() -> new ResourceNotFoundException("User", "id", id)
);
return UserPrincipal.create(client);
}
UserPrincipal:
public class UserPrincipal implements UserDetails {
private Long id;
private String name;
private String username;
@JsonIgnore
private String email;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public UserPrincipal(Long id, String name, String username, String email, String password, Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.name = name;
this.username = username;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserPrincipal create(Client client) {
List<GrantedAuthority> authorities = client.getRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getName().name())
).collect(Collectors.toList());
return new UserPrincipal(
client.getId(),
client.getName(),
client.getUsername(),
client.getEmail(),
client.getPassword(),
authorities
);
}
ClientRepository:
@Repository
public interface ClientRepository extends JpaRepository<Client, Long> {
Optional<Client> findByUsernameOrEmail(String username, String email);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
Не могли бы вы сказатьмне где может быть проблема?Если требуется больше кода, я могу прикрепить его, но, пожалуйста, скажите, к какому классу.
Единственное, что отличается в базе данных - это «Тип» - другая информация такая же.
Я знаю, что могуобъединить каждую переменную с родительским классом, но возможно ли выполнить вход с наследованием?
РЕДАКТИРОВАТЬ - ЛОГИ:
2018-12-10 22:41:41.241 DEBUG 9499 --- [nio-8080-exec-3] org.hibernate.SQL : select * from clients c where c.username = ? or c.email = ?
2018-12-10 22:41:41.242 TRACE 9499 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [thomas]
2018-12-10 22:41:41.242 TRACE 9499 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [thomas]
2018-12-10 22:41:41.248 DEBUG 9499 --- [nio-8080-exec-3] org.hibernate.SQL : select roles0_.user_id as user_id1_15_0_, roles0_.role_id as role_id2_15_0_, role1_.id as id1_14_1_, role1_.name as name2_14_1_ from user_roles roles0_ inner join roles role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
2018-12-10 22:41:41.249 TRACE 9499 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]
2018-12-10 22:41:49.718 DEBUG 9499 --- [nio-8080-exec-4] org.hibernate.SQL : select * from clients c where c.username = ? or c.email = ?
2018-12-10 22:41:49.718 TRACE 9499 --- [nio-8080-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [anthony]
2018-12-10 22:41:49.718 TRACE 9499 --- [nio-8080-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [anthony]
Первый выбор - это когда тип равен RetailClient, а второй - когда я меняюэто для «Клиента», после этого идет утверждение ролей, и все работает ...