2016-03-01 44 views
1

我試圖實現自定義註釋,因爲它寫在這個post,但出了點問題。當我試圖在dataBase中堅持我的實體時,它會用我的自定義註釋來無限檢查字段。我使用wildfly 9.0.2無限檢查自定義JSR303註釋

代碼:

實體:

@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; 
    } 
} 

的UserManager:

@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)

預先感謝您!

+0

你說你正在進入一個無限循環。這是否意味着你必須殺死這個過程?或者,此錯誤是否出現在持久存儲的日誌中,並且服務器繼續運行? – Hardy

+0

服務器停止響應,我所能做的就是終止服務器進程。 –

+0

@MaxMax JPA規範指出,不要在entitylistener中調用另一個db調用,否則會導致無限循環。我想這也適用於約束驗證,因爲它們也在jpa事務中執行,另一個db調用將導致再次調用相同的約束驗證程序。 – maress

回答

1

所以問題是,當我從我的驗證器調用,它需要父事務以及@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; 
    }