Доступ к базе данных из пользовательского валидатора jsr-303 - PullRequest
3 голосов
/ 06 июля 2011

Я использую пружинную валидацию в сочетании с валидатором гибернации, включенным следующим образом в контексте моего приложения:

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

Это приводит к исключению "сбор не обработан с помощью flush ()"из спящего

Существует ли пример наилучшей практики доступа к базе данных из пользовательского валидатора, который позволит мне обойти обе эти проблемы?

Ответы [ 2 ]

1 голос
/ 25 ноября 2011

После долгих экспериментов может показаться, что лучший способ сделать это - использовать EntityManagerFactory непосредственно из кода. В методе initialize (...) класса валидатора у меня есть следующий код:

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

Недостатком является то, что вы не получаете функции Spring DI, но тем не менее вы можете получить доступ к базе данных.

0 голосов
/ 18 декабря 2012

Я тоже столкнулся с этой проблемой, вот как я ее решил: @ Компонент Autowired работает с @Valid на контроллере, но не работает с репозиторием CRUD

В нескольких словах я также получил ссылку на объект 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);
           }    
    }
}
...