【问题标题】:Making Spring 3 MVC controller method Transactional使 Spring 3 MVC 控制器方法具有事务性
【发布时间】:2012-10-19 10:01:31
【问题描述】:

我正在使用 Spring 3.1 并编写了我的 DAO 和服务层(事务)。

但是在特殊情况下,为了避免惰性初始化异常,我必须创建一个 spring mvc 请求处理程序方法@transactional。但它未能将事务附加到该方法。方法名称是 ModelAndView home(HttpServletRequest request, HttpServletResponse response)。 http://forum.springsource.org/showthread.php?46814-Transaction-in-MVC-Controller 从这个链接似乎不可能将事务(默认情况下)附加到 mvc 方法。该链接中建议的解决方案似乎适用于 Spring 2.5(覆盖 handleRequest )。任何帮助将不胜感激。谢谢

@Controller
public class AuthenticationController { 
@Autowired
CategoryService categoryService;    
@Autowired
BrandService brandService;
@Autowired
ItemService itemService;

@RequestMapping(value="/login.html",method=RequestMethod.GET)
ModelAndView login(){       
    return new ModelAndView("login.jsp");       
}   
@RequestMapping(value="/home.html",method=RequestMethod.GET)
@Transactional
ModelAndView home(HttpServletRequest request, HttpServletResponse response){
    List<Category> categories = categoryService.readAll();
    request.setAttribute("categories", categories);     
    List<Brand> brands = brandService.readAll();
    request.setAttribute("brands", brands);     
    List<Item> items = itemService.readAll();
    request.setAttribute("items", items);
    Set<Image> images = items.get(0).getImages();
    for(Image i : images ) {
        System.out.println(i.getUrl());
    }
    return new ModelAndView("home.jsp");    
}

【问题讨论】:

  • 你想在这里回滚什么?在您定义了 @Transaction 注释的控制器函数上,没有可以回滚的数据库操作。我很困惑。
  • 所有像 categoryService.readAll() 这样的服务调用都是数据库操作
  • 是的,但你不能回滚读取的数据。你到底想回滚什么?
  • 将 home 方法包装在事务中仍然很有用,因为它可能有助于共享数据库连接
  • 是的,连接将被共享,延迟加载也只能在同一个会话中工作。

标签: java spring hibernate jakarta-ee spring-mvc


【解决方案1】:

您需要实现一个接口,以便 Spring 拥有可以用作代理接口的东西:

@Controller
public interface AuthenticationController {
  ModelAndView home(HttpServletRequest request, HttpServletResponse response);
}

@Controller
public class AuthenticationControllerImpl implements AuthenticationController {

@RequestMapping(value="/home.html",method=RequestMethod.GET)
@Transactional
@Override
ModelAndView home(HttpServletRequest request, HttpServletResponse response){
.....
}
}

【讨论】:

  • 使用 springBoot 1.2.3.RELEASE 和 spring 4.1.6.RELEASE 我遇到完全相反的情况:如果控制器 (@RequestMapping) 正式实现了一个接口,spring 创建一个 JdkDynamicAopProxy (它启动时没有错误但调度程序 servlet 在运行时找不到 URL 映射的入口点)。如果控制器没有正式实现接口,则会生成 CglibAopProxy,并且一切正常。与下面 chrismarx 的注释相反,CGLib 不需要是显式依赖项。
【解决方案2】:

Spring 将使用 JDK 动态代理来实现事务逻辑,这些代理依赖于实现合适接口的代理类。也可以使用不需要接口的 CGLib 代理。

关于这个link有一篇不错的文章

【讨论】:

  • 我认为这是更好的答案,如果您不指定接口,Spring 将尝试为控制器创建 cglib 代理,并且只要 cglib 在类路径上,这一切都可以正常工作,并且你不需要处理任何改变。我遇到了@requestmapping 试图让具有接口的控制器工作的问题
  • 此链接已更改为spring.io/blog/2012/05/23/…
【解决方案3】:

我不确定这是否适用于您的情况,但如果您使用单独的 DI 上下文,您还应该考虑 Spring 如何编织方面。

Spring 只会将 @Transactional 语义应用于使用 @EnableTransactionManagement&lt;tx:annotation-driven/&gt; 的同一 DI 上下文中的 bean。

因此,如果您在根上下文中定义事务配置,则仅涵盖该上下文中的 bean,这通常意味着仅业务服务。 您需要在还使用@Transactional 的任何子上下文中重新启用事务管理。

参考: Spring AOP - How to make aspects defined in a parent context work in child contexts?

【讨论】:

    猜你喜欢
    • 2013-09-09
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多