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層。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM