Seb*_*ian 5 java spring-mvc transactional hibernate-validator hibernate-4.x
我正在尝试为 Rest API 实现注册控制器。我已经阅读了很多关于放置@Transactional 的内容。(不是在 DAO 级别,而是在可能编排的服务)。在我的用例中,我不仅需要服务,还需要休眠验证来使用相同的事务。
这是控制器的代码:
@Autowired
private UserService userService;
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@Transactional
public DefaultResponse register(@Valid RegisterIO registerIO, BindingResult errors) {
DefaultResponse result = new DefaultResponse();
if (errors.hasErrors()) {
result.addErrors(errors);
} else {
userService.register(registerIO);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我编写了一个自定义约束注释,它验证参数 registerIO 的属性。两者,这个验证器和 userService.register(registerIO); 访问数据库(检查电子邮件地址是否已被使用)。
因此我希望这两种方法都使用相同的 Hibernate 会话和事务。
这种方法导致以下异常:
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)
Run Code Online (Sandbox Code Playgroud)
问题是@Transactional 注释。当我将此注释放在调用数据库的方法上时,一切正常,但两个事务都开始了。我怀疑当我将它放在 register 方法中时,在 @Transactional 启动此方法的事务之前执行休眠验证。
我开发了以下功能解决方法,但我对此并不满意。此代码不使用 @Valid 注释而是自行调用验证器:
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@Transactional
public DefaultResponse register( RegisterIO registerIO, BindingResult errors) {
DefaultResponse result = new DefaultResponse();
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();
Set<ConstraintViolation<RegisterIO>> valResult = validator.validate(registerIO);
Run Code Online (Sandbox Code Playgroud)
我尝试总结一下我的问题:将 Spring MVC 和 Hibernate-Validation 与 @Valid 和 @Transactional 一起使用,如何将整个请求封装到一个事务中?
谢谢 :)
您可以通过使用单个验证器并将其注入控制器来改进您的解决方法。你有没有尝试过:
@Autowired
private Validator validator;
Run Code Online (Sandbox Code Playgroud)
这样您就可以跳过在每个请求上创建验证器的开销。您还应该小心竞争条件。当您检查数据库是否存在给定电子邮件时,另一个请求可以创建此记录,以便您在插入数据时仍然会遇到异常。
| 归档时间: |
|
| 查看次数: |
1403 次 |
| 最近记录: |