【问题标题】:infinite check for custom JSR303 annotation无限检查自定义 JSR303 注释
【发布时间】:2016-03-01 14:58:18
【问题描述】:

我正在尝试实现自定义注释,因为它是在这个post 中编写的,但是出了点问题。当我试图将我的实体保存在数据库中时,它会使用我的自定义注释无限检查字段。我正在使用 Wildfly 9.0.2

代码:

实体:

@Entity
@Table(name = "users")
@NamedQueries({
        @NamedQuery(name = User.FIND_BY_LOGIN_AND_USERNAME,query = "SELECT u FROM User u WHERE u.userName = :username and u.password = :password"),
        @NamedQuery(name = User.FIND_USER_BY_USERNAME,query = "SELECT u FROM User u WHERE u.userName = :username")
})
public class User implements Serializable{

    public static final String FIND_BY_LOGIN_AND_USERNAME = "findByLoginAndPassword";
    public static final String FIND_USER_BY_USERNAME = "findUserByUsername";

    @Id
    @GeneratedValue
    private Long id;
    @NotNull
    @Size(min = 3,max = 64,message = "{model.User.login.message}")
    @Username
    @Column(name = "user_name",nullable = false,unique = true)
    private String userName;

    //...other fields...

    //...constructors, getters and setters...
}

注释:

@Constraint(validatedBy = UsernameValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
public @interface Username {
    String message() default "Username already exists";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

验证器:

public class UsernameValidator implements ConstraintValidator<Username, String> {

    @Inject
    UserManager userManager;

    @Override
    public void initialize(Username constraintAnnotation) {

    }

    @Override
    public boolean isValid(String username, ConstraintValidatorContext context) {
        boolean isValid = !userManager.userExist(username);
        return isValid;
    }
}

用户管理器:

@Stateless
public class UserManager {

    @PersistenceContext(unitName = "MySqlPU")
    EntityManager em;

    public void persist(User user){
        em.persist(user);
    }

    public User findUserByLoginAndPassword(String username, String password) {
        try {
            return em.createNamedQuery(User.FIND_BY_LOGIN_AND_USERNAME, User.class)
                    .setParameter("username",username)
                    .setParameter("password",password)
                    .getSingleResult();
        } catch (NoResultException e){
            return null;
        }
    }

    public boolean userExist(String username) {
        try {
            em.createNamedQuery(User.FIND_USER_BY_USERNAME, User.class)
                    .setParameter("username", username)
                    .getSingleResult();
        } catch (NoResultException e) {
            return false;
        }
        return true;
    }
}

链接到server.log (snip2code)

提前谢谢你!

【问题讨论】:

  • 你说你正在进入一个无限循环。这是否意味着您必须终止该进程?还是这个错误出现在persist的日志中,服务器继续运行?
  • 服务器停止响应,我只能杀死服务器进程。
  • @MaxMax JPA 规范指出,永远不要在 entitylistener 中调用另一个 db 调用,否则会导致无限循环。我想这也适用于约束验证,因为它们也在 jpa 事务中执行,另一个 db 调用将导致再次调用相同的约束验证器。

标签: java jpa jakarta-ee bean-validation


【解决方案1】:

所以问题是,当我从验证器调用userExist(String username) 时,它需要父事务以及@maress 所说的,进入无限循环。我通过在userExist 方法禁用事务来解决此问题。所以现在有了这个改变,代码就可以工作了

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public boolean userExist(String username) {
        try {
            em.createNamedQuery(User.FIND_USER_BY_USERNAME, User.class)
                    .setParameter("username", username)
                    .getSingleResult();
        } catch (NoResultException e) {
            return false;
        }
        return true;
    }

【讨论】:

    猜你喜欢
    • 2013-07-13
    • 2017-03-01
    • 2011-01-11
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多