2011-07-06 164 views
3

我使用基于弹簧的验证与在我的应用程序环境下启用Hibernate验证组合:数据库访问

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     .... 
     <property name="jpaPropertyMap"> 
      <map> 
       <entry key="javax.persistence.validation.factory" value-ref="validator" />  
      </map> 
     </property> 
    </bean> 

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 

,我实现了访问数据库的自定义验证使用弹簧注入的DAO来检查特定对象的有效性约束。这会导致java.lang.StackOverflowError,因为看起来每次从验证器中的数据库加载对象时都会调用验证,导致无限循环。为了解决这个问题,我已经尝试设置我的实体管理器的刷新模式,从下面的代码验证器内提交:

entityManager.setFlushMode(FlushModeType.COMMIT); 

这将导致“被刷新集合无法处理()”从休眠状态中的异常。

是否有一个从自定义验证程序中访问数据库的最佳实践示例,这将允许我解决这两个问题?

+0

类似的问题:http://stackoverflow.com/questions/8375704/make-custom-hibernate-validation-annotation-for-电子邮件存在IMHP春天的方式是'@ Autowired'服务或DAO类的验证和通常使用它们。 –

回答

1

经过大量的实验,看起来最好的方法是直接从代码中使用EntityManagerFactory。在验证器类的初始化(...)方法,我有以下代码:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu_name"); 
entityManager = emf.createEntityManager(); 

的缺点是,你没有得到Spring的DI功能,但你仍然可以访问数据库。

0

我就遇到了这个问题为好,这里是我如何解决它: @Autowired bean works with @Valid on controller but fails with CRUD repository

几句话,我也到了EntityManagerFactory对象的引用。但是,在拨打我的服务方式之前,我将setFlushMode设置为FlushModeType.COMMIT。最后,我把它设回FlushModeType.AUTO

下面是一个例子:

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> { 

    @PersistenceContext 
    private EntityManager em; 

    @Autowired 
    UserService userService; 

    @Override 
    public void initialize(UniqueUsername constraintAnnotation) {  
    } 

    @Override 
    public boolean isValid(String username, ConstraintValidatorContext context) { 
     try { 
      em.setFlushMode(FlushModeType.COMMIT);   
      return userService.findByUsername(username) == null; 

      } finally { 
      em.setFlushMode(FlushModeType.AUTO); 
      }  
    } 
}