zoukankan      html  css  js  c++  java
  • springmvc的controller中使用@Transactional无效

    最近看mybatis的时候做了一个练习,但是进行事务处理的时候出了问题,如下

    复制代码
    package com.henu.lz.controller;  
      
    import org.springframework.beans.factory.annotation.Autowired;  
    import org.springframework.stereotype.Controller;  
    import org.springframework.transaction.annotation.Transactional;  
    import org.springframework.ui.Model;  
    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.bind.annotation.RequestParam;  
      
    import com.henu.lz.dao.PersonMapper;  
    import com.henu.lz.model.Person;  
      
    @Controller  
    public class SupplierController {  
          
        @Autowired  
        PersonMapper personMapper;  
          
        @Transactional  
        @RequestMapping("/add")  
        public String addPerson(  
                @RequestParam("name1") String name1,  
                @RequestParam("age1") int age1,  
                @RequestParam("name2") String name2,   
                @RequestParam("age2") int age2,   
                Model model) {  
              
            Person person1 = new Person();  
            Person person2 = new Person();  
            person1.setName(name1);  
            person1.setAge(age1);  
            person2.setName(name2);  
            person2.setAge(age2);  
              
            personMapper.save(person1);  
            personMapper.save(person2);  
              
            model.addAttribute("message", "添加成功!");  
            return "success";  
        }  
    }  
    复制代码

    spring容器和springmvc的配置都没有问题,dao层就是mybatis比较与众不同的的写有sql的xml以及接口。在从前台传值的时候person1正常传,person2传能抛SQLException的值,按理说事务应该回滚的,数据库中不会有person1,但是查看数据库却有person1。用的mysql,引擎设置为innodb后还是这样,换了oracle之后依然如此。这两次save不在一个事务。

    网上看了下别人的经历,有的是try…catch之后自行处理没有throw,有的是说设置rollbackFor……有一个比较接近

    http://www.iteye.com/topic/714686

    用的是 hibernate 3.2,在配置dao和controller的时候都用了注解方式自动扫描

    <context:component-scan base-package="com..." />  

    这样说是导致dao中事务无效,我试过这样配置,服务启动直接就出错了,很显然冲突,而且用context:include-filter和context:exclude-filter来屏蔽掉controller层的解决办法也有点没必要,分别扫描dao层和controller层不就行了,我是这样配置的。

    查看mybatis官网上的project,是比我多了一层service层,然后在service中用的@transactional,我加了一层

    复制代码
    package com.henu.lz.service;  
      
    import org.springframework.beans.factory.annotation.Autowired;  
    import org.springframework.stereotype.Service;  
    import org.springframework.transaction.annotation.Transactional;  
      
    import com.henu.lz.dao.PersonMapper;  
    import com.henu.lz.model.Person;  
      
    @Service(value="personService")  
    public class PersonServiceImpl implements PersonService {  
          
        @Autowired  
        private PersonMapper personMapper;  
          
        @Transactional  
        public void save(Person p1, Person p2) {  
            personMapper.save(p1);  
            personMapper.save(p2);  
        }  
      
    }  
    复制代码

    相应的,controller也修改为

    复制代码
    package com.henu.lz.controller;  
      
    import javax.annotation.Resource;  
      
    import org.springframework.stereotype.Controller;  
    import org.springframework.ui.Model;  
    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.bind.annotation.RequestParam;  
    import com.henu.lz.model.Person;  
    import com.henu.lz.service.PersonService;  
      
    @Controller  
    public class SupplierController {  
          
        @Resource  
        private PersonService personService;  
          
        @RequestMapping("/add")  
        public String addPerson(  
                @RequestParam("name1") String name1,  
                @RequestParam("age1") int age1,  
                @RequestParam("name2") String name2,   
                @RequestParam("age2") int age2,   
                Model model) {  
              
            Person person1 = new Person();  
            Person person2 = new Person();  
            person1.setName(name1);  
            person1.setAge(age1);  
            person2.setName(name2);  
            person2.setAge(age2);  
      
            personService.save(person1, person2);  
              
            model.addAttribute("message", "添加成功!");  
            return "success";  
        }  
    }  
    复制代码

    这时再按开始那样传值能得到预期结果了。

    一开始也注意到少了一层service,但是觉得在controller中做同样的事情也可以的,所以就杯具了。

    因为spring的context和mvc是分开的,貌似controller不能被注册到spring的context中,于是不能被transactionManager拦截,那么controller中那个@transactional就不起作用了。看了声明式事务的五种配置,都是对注册到context中的bean起作用的,不论是拦截器方式还是aop:config方式。

    事务注解方式不能应用于接口,我的mapper用的又是xml方式的,所以只能加一层service,然后controller中的交易就放在service层。

  • 相关阅读:
    api
    git分支合并
    Zookeeper 入门,看这篇就够了
    SQL分组查询
    [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:lovemu' did not find a matching property.
    事务 事务隔离级别
    DDL DML DCL的理解
    局域网和广域网
    三种数据交换方式
    通信子网和资源子网
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/14501595.html
Copyright © 2011-2022 走看看