hibernate 使用Spring进行自定义唯一用户名验证

vd8tlhqk  于 2023-01-05  发布在  Spring
关注(0)|答案(2)|浏览(179)

我想确保用户名是唯一的,当创建一个新的用户名或更新一个用户名.我写了下面的代码,它可以很好地创建和更新用户名.但当只更新其他用户字段,如年龄或性别,并保持相同的用户名,它返回无效,因为用户名已经存在.
需要说明的是,我想要使用BindingResult进行验证。我已经有了一个将用户名视为唯一约束的数据库。但是现在我想要使用BindingResult进行相同的验证。但是我所做的方式在更新用户时会导致错误。
定义注解@UniqueUsername

package app.condominio.validator;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueUsername {
    String message() default "Nome de usuário já está sendo usado";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

实现验证器

package app.condominio.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.beans.factory.annotation.Autowired;

import app.condominio.service.UsuarioService;

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {

    @Autowired
    UsuarioService usuarioService;

    @Override
    public void initialize(UniqueUsername username) {
    }

    @Override
    public boolean isValid(String username, ConstraintValidatorContext cxt) {
        return !usuarioService.existe(username);
    }
}

在常规类中

@Entity
@Table(name = "Usuarios")
public class Usuario implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank
@UniqueUsername
private String username;

@NotBlank
private String password;

@NotBlank
private String nome;

@Email
private String email;

...

惯常服务

@Service
@Transactional
public class UsuarioServiceImpl implements UsuarioService {

    @Autowired
    private UsuarioDao usuarioDao;

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public boolean existe(String username) {
        return usuarioDao.existsByUsername(username);
    }

臼生道

public interface UsuarioDao extends CrudRepository<Usuario, Long> {

    Usuario findByUsername(String username);
    
    Boolean existsByUsername(String username);

}

主计长

@Controller
@RequestMapping("conta")
public class UsuarioController {

    @Autowired
    private UsuarioService usuarioService;

    @GetMapping("/cadastrar/sindico")
    public ModelAndView preCadastro(@ModelAttribute("usuario") Usuario usuario, ModelMap model) {
        model.addAttribute("conteudo", "cadastrarSindico");
        return new ModelAndView("site/layout", model);
    }

    @PostMapping("/cadastrar/sindico")
    public ModelAndView posCadastro(@Valid @ModelAttribute("usuario") Usuario usuario, BindingResult validacao, ModelMap model) {
        if (validacao.hasErrors()) {
            return preCadastro(usuario, model);
        }
        usuarioService.salvarSindico(usuario);
        model.addAttribute(usuario);
        model.addAttribute("conteudo", "cadastrarCondominio");
        return new ModelAndView("site/layout", model);
    }
nmpmafwu

nmpmafwu1#

我认为UniqueUsernameValidator的行动符合预期。
我对你的应用不是很清楚,所以很难实现一个方法来检查验证用户是否与数据库中的用户具有相同的ID。可能你应该提供更多的细节,例如方法usuarioService.existe(username)的代码。
对于我来说,为了确保用户名是唯一的,我这样做:

@Column(unique=true)
String username;

或使用@唯一约束

@Table(name = "users", uniqueConstraints = {
    @UniqueConstraint(columnNames = {
        "username"
    })
})

但是注意如果您让JPA创建表,它也会工作。

  • @唯一约束
hyrbngr7

hyrbngr72#

您可以尝试使用验证组的以下方法:
创建标记接口(或类)

public interface UserCreateValidationGroup {
}

然后在实体中使用它,如下所示

@NotBlank
@UniqueUsername(groups = UserCreateValidationGroup.class)
private String username;

然后在Controller中与@Validated(Spring的JSR-303变体)沿着使用它。注意,您必须将单个方法拆分为单独的创建和更新方法,以区分验证。
创建:

@PostMapping("/cadastrar/sindico")
public ModelAndView create(
    @Validated(UserCreateValidationGroup.class) @ModelAttribute("usuario") Usuario usuario, 
    BindingResult validacao, 
    ModelMap model
) { ... }

更新:

// note, here I did use PUT and no argument for @Validated annotation
@PutMapping("/cadastrar/sindico") 
public ModelAndView update(
    @Validated @ModelAttribute("usuario") Usuario usuario, 
    BindingResult validacao, 
    ModelMap model
) { ... }

但是,在更新情况下,您必须手动检查(UsuarioService.existe)用户名。

相关问题