Код: Выделить всё
RegisterRequestКод: Выделить всё
UsuarioКод: Выделить всё
firstNameОднако реализация, сгенерированная mapstruct , - это шифрование все Fields, которая вызывает ошибку длины:
Код: Выделить всё
value too long for type character varying(30)В столбце FirstName, который имеет предел 30-характера, в то время как сгенерированные хэши составляют приблизительно 60 символов. делегируйте эту работу и уменьшите код шаблона. Поток, который мне нужен, был:
[*] Получить запрос POST с помощью RegisterRequest , содержащий электронную почту , пароль , FirstName и lastname . mapStruct .
[*] зашифровать только пароль Поле с использованием passwordEncoder .
[*] Назначать постоянное значение «пользователь» Сохранить usuario < /code> в базе данных без какой -либо ошибок длины.
Код: Выделить всё
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface UsuarioRegisterMapper {
@Mapping(target = "rol", constant = "User")
@Mapping(target = "id", ignore = true)
@Mapping(target = "contrasena", expression = "java(encodePassword(request.contrasena(), passwordEncoder))")
Usuario toEntity(RegisterRequest request, @Context PasswordEncoder passwordEncoder);
default String encodePassword(String rawPassword, @Context PasswordEncoder passwordEncoder) {
return passwordEncoder.encode(rawPassword);
}
}
< /code>
Реализация, автоматически сгенерированная Mapstruct: < /p>
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-07-14T21:19:15-0600",
comments = "version: 1.5.5.Final, compiler: javac, environment: Java 23.0.2 (Oracle Corporation)"
)
@Component
public class UsuarioRegisterMapperImpl implements UsuarioRegisterMapper {
@Override
public Usuario toEntity(RegisterRequest request, PasswordEncoder passwordEncoder) {
if (request == null) {
return null;
}
Usuario usuario = new Usuario();
usuario.setNombre(encodePassword(request.nombre(), passwordEncoder));
usuario.setApellido(encodePassword(request.apellido(), passwordEncoder));
usuario.setEmail(encodePassword(request.email(), passwordEncoder));
usuario.setRol(encodePassword("User", passwordEncoder));
usuario.setContrasena(encodePassword(request.contrasena(), passwordEncoder));
return usuario;
}
}
< /code>
package com.proyectoUno.security.dto;
public record RegisterRequest(
String email,
String contrasena,
String nombre,
String apellido
) {}
< /code>
@Service
public class AuthService {
// ... (injections)
public AuthResponse register(RegisterRequest request) {
if (usuarioRepository.findByEmail(request.email()).isPresent()) {
throw new EntidadDuplicadaException("Email is already associated with an account", "email", Collections.singletonList(request.email()));
}
// This is where I use the mapper to skip the manual process of instantiating the class and calling .set for each value
Usuario usuario = usuarioRegisterMapper.toEntity(request, this.passwordEncoder);
System.out.println("Usuario before saving: " + usuario);
usuarioRepository.save(usuario);
UserDetails userDetails = new CustomUserDetails(usuario);
String jwtToken = jwtService.generateAccessToken(userDetails);
String refreshToken = jwtService.generateRefreshToken(userDetails);
return new AuthResponse(jwtToken, refreshToken);
}
// ...
}
< /code>
Postman:
{
"email": "mario.rodriguez@gmail.com",
"contrasena": "soyMario1050",
"nombre": "Mario",
"apellido": "Rodriguez"
}
< /code>
After sending the request from Postman, the bug appeared. To verify it was caused by the Mapper configuration, I did some quick debugging to check the mapper’s output.
Usuario before saving: Usuario{id=null,
nombre='$2a$10$SKiTvYYJK.vZPetwOtY1OOBMCz6m15.bSUCZzk67Q..Ybs0h0n6nu',
apellido='$2a$10$h/PjGAv8aF7sGdCMo7jK/.CaHfcS.e1bHGIM28bb/RIYd/t1CL0jy',
email='$2a$10$ookM1PA26edcSu0mt4FnZegsvg/Cm3S0zdp5aRmfY/e1pcJ7TqT8K',
contrasena='$2a$10$aMIQJAo/pX7TEWhbKwtj/O0x/yuy8eqkfMVBfY7..fmnnmcwLo1e.',
rol='$2a$10$WV1kZvIx.j/UZfCSmcPMoOvOMFXXUM.qDKIarD5rIOLAHThULlUKK',
fechaRegistro=null, activo=false, prestamo=[]}
< /code>
And that’s when the issue became clear: the mapper wasn’t just handling the password, что я попробовал
Id -enflicit mappings in uSuariARIGER. apellido и email (например, @mapping (target = "nombre", source = "request.nombre") ), но сгенерированная реализация все еще применяет encodepassword ко всем полям. сохраняется.
I подтвердил, что таблица USUario имеет правильную длину столбцов (например, Nombre как varchar (30) ), но сгенерированные хэши превышают этот предел. /> Вопрос
Почему Mapstruct шифрует все поля с помощью пароля. Другие поля отображаются напрямую? < /p>
< /li>
Есть ли ошибка в версии Mapstruct 1.5.5.final с Java 23.0.2? Заранее спасибо.
Подробнее здесь: https://stackoverflow.com/questions/797 ... y-the-pass