Spring MVC:mvc控制器上的conversionservice和@transactional问题

时间:2014-04-14 14:28:07

标签: spring spring-mvc type-conversion transactional

我通过在MVC控制器中将LazyInitializationExceptionconversionservice行为相结合来获得@Transactional

以下失败:

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
@ResponseBody
@Transactional
public JsonUser getUser(@PathVariable("userId") User user) {
    // convertToJsonUser triggers lazy loading of User.adresses
    return mUserPresenter.convertToJsonUser(user);
}

...以下例外情况:     org.hibernate.LazyInitializationException:懒得初始化角色集合:User.adresses,无法初始化代理 - 没有会话

但没有转换服务的相同代码成功:

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
@ResponseBody
@Transactional
public JsonUser getUser(@PathVariable("userId") Long userId) {
    User user = mUserRepository.findOne(userId);
    // convertToJsonUser triggers lazy loading of User.adresses
    return mUserPresenter.convertToJsonUser(user);
}

并且没有事务行为的相同代码成功:

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
@ResponseBody
public JsonUser getUser(@PathVariable("userId") User user) {
    // changedConvertToJsonUser DOESN'T trigger lazy loading of User.adresses
    return mUserPresenter.changedConvertToJsonUser(user);
}

@Transactional注释要打开的主要事务之前,转换似乎发生在自己的事务中。因此,转换管理器加载的User是因为这个原因,没有绑定到主事务,延迟加载失败。

  • 这种行为是否已知?
  • 我该怎样摆脱它?
  • 我是否忘记了配置中的某些内容?

提前谢谢!!!

2 个答案:

答案 0 :(得分:0)

控制器不是放置@Transactional注释的理想场所。最好将它们添加到服务方法中。这可能会导致问题,因为您可能有一个控制器的代理对象,它与事务管理器中的代理混淆,您无法预测执行的顺序。所以我的建议是:尝试添加一个服务层..即使是非常简单的将@Transactional注释放在那里并再次测试代码。

答案 1 :(得分:0)

  

...转换服务本身就是加载实体的方式......

不,不是。这就像名称所示:转换。如果你加载实体,那么这是你的选择,而不是Spring的。

  

如果不建议在控制器层中打开事务,那么为什么Spring开发人员已经开发了转换服务功能?

ConversionService中的服务表示我们在控制器层中

  

转换似乎发生在自己的事务中,然后由@Transactional注释打开主事务

在这种情况下,@Transactional没有打开任何交易,因为它不起作用。

交易通常适用于服务层。你可以有类似的东西:

MyUserService implements UserService  {
  @Override
  @Transactional(readonly = true)
  public User getUserById(int id) {

但那不是你的问题。您的问题是User对象未完全初始化。您需要convertToJsonUser上的交易。

作为旁注:开发Spring的人更喜欢直接使用id并在控制器中加载实体,而不是之前。