您的位置:首页 > 编程语言 > Java开发

Spring+Mybatis整合事务不起作用之…

2013-09-11 15:58 232 查看
前言:

公司最近一个项目用到Spring和Mybatis,发现用起来挺方便,比以前的那个struts+hibernate舒服多了。废话少说,直接摆问题,碰到的问题是,mybatis不在事务中运行,后台日志报
“ClosingnotransactionalSqlSession[org.apache.ibatis.session.defaults.DefaultSqlSession@19006c9]”错误。无论是加了@Transactional注解和是没加都报这个信息。一个方法中插入多条数据,某次插入失败也不回滚。



问题描述:

环境:Spring3.1.0+Mybatis3.1.0+mybatis-spring1.0.0RC3+
DB29.5+Tomcat6.0.35

web工程名称:isap

配置文件:applicationContext.xml+isap-servlet.xml

先看配置信息:

applicationContext.xml

查看源码

打印?

01
<?
xml
version
=
"1.0"

encoding
=
"UTF-8"
?>
02
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
03
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
04
xmlns:tx
=
"http://www.springframework.org/schema/tx"
05
xmlns:context
=
"http://www.springframework.org/schema/context"
06
xsi:schemaLocation="
07
http://www.springframework.org/schema/beans
08
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
09
http://www.springframework.org/schema/tx
10
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
11
http://www.springframework.org/schema/context
12
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
13
14
15
<!--
spring配置jndi-->
16
<
bean

id
=
"dataSource"

class
=
"org.springframework.jndi.JndiObjectFactoryBean"
>
17
<
property

name
=
"jndiName"
>
18
<
value
>java:comp/env/jndi_isap</
value
>
19
</
property
>
20
</
bean
>
21
22
<
bean

id
=
"sqlSessionFactory"
class
=
"org.mybatis.spring.SqlSessionFactoryBean"
>
23
<
property

name
=
"configLocation"
value
=
"classpath:config/mybatis-config.xml"
></
property
>
24
<
property

name
=
"dataSource"

ref
=
"dataSource"
/>
25
<
property

name
=
"mapperLocations"
>
26
<
list
>
27
<
value
>classpath:com/cosbulk/isap
13
public

LonggetId()
{
14
return

userDao.getId();
15
}
16
17
22
public

void
updateUser(User
user,Map<String,Object>param)
{
23
//编辑用户
24
userDao.updateUser(user);
25
//删除原有的用户角色关联
26
userDao.deleteUserRole(param);
27
String
s=
null
;
28
s.getBytes();
29
//新增用户角色关联
30
insertUserRole(param);
31
}
32
这里用来测试事务回滚
33
...
34
}
测试过几次updateUser的调用,事务就是不起作用的,后台log信息如下:



查看源码

打印?

1
DEBUG

2011
-
09
-
04

16
:
19
:
46
,
672

org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl:
JDBCConnection
[org.apache.commons.dbcp.PoolableConnection
@67aece
]willnotbe
managedbySpring
2
3
DEBUG

2011
-
09
-
04

16
:
19
:
46
,
672

org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl:
SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession
@19006c9
]
wasnotregistered
for

synchronizationbecausesynchronizationis
notactive
4
5
DEBUG

2011
-
09
-
04

16
:
19
:
46
,
687

org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl:
CommittingJDBCConnection
[org.apache.commons.dbcp.PoolableConnection
@67aece
]
6
7
DEBUG

2011
-
09
-
04

16
:
19
:
46
,
687

org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl:
ClosingnotransactionalSqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession
@19006c9
]
8
9
DEBUG

2011
-
09
-
04

16
:
19
:
46
,
687

org.springframework.jdbc.datasource.DataSourceUtils:
ReturningJDBCConnectiontoDataSource
解决方案:

1、配置文件的问题吧?
(见http://www.iteye.com/topic/1123069)

查看源码

打印?

01
1.root-context.xml
02
<!--
不扫描带有@Controller注解的类。因为这些类已经随容器启动时,在servlet-context中扫描过一遍了
-->
03
<
context:component-scan
base-package
=
"com.kimho"
>
04
<
context:exclude-filter
type
=
"annotation"

expression
=
"org.springframework.stereotype.Controller"
/>
05
</
context:component-scan
>
06
07
2、servlet-context.xml:
08
<!--
扫描业务组件,让spring不扫描带有@Service注解的类(留在root-context.xml中扫描@Service注解的类),防止事务失效
-->
09
<
context:component-scan
base-package
=
"com.kimho"
>
10
<
context:exclude-filter
type
=
"annotation"

expression
=
"org.springframework.stereotype.Service"
/>
11
</
context:component-scan
>
我做了相应的修改,把isap-servlet里的bean扫描拆成了两部分,分别放入applicationContext.xml和isap-servlet.xml文件中。

applicationContext.xml中加入:

查看源码

打印?

1
<!--
扫描带有@Service注解的类。-->
2
<
context:component-scan

base-package
=
"com.cosbulk.isap"
>
3
<
context:include-filter

type
=
"annotation"

expression
=
"org.springframework.stereotype.Service"

/>
4
</
context:component-scan
>
5
6
<
context:component-scan

base-package
=
"com.cosbulk.smis"
>
7
<
context:include-filter

type
=
"annotation"

expression
=
"org.springframework.stereotype.Service"

/>
8
</
context:component-scan
>
isap-servlet.xml文件中,扫描bean部分换成:

查看源码

打印?

1
<!--排除扫描的包,
对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能-->
2
<
context:component-scan

base-package
=
"com.cosbulk.isap"
>
3
<
context:exclude-filter

type
=
"annotation"

expression
=
"org.springframework.stereotype.Service"
/>
4
</
context:component-scan
>
5
6
<
context:component-scan

base-package
=
"com.cosbulk.smis"
>
7
<
context:exclude-filter

type
=
"annotation"

expression
=
"org.springframework.stereotype.Service"
/>
8
</
context:component-scan
>
重启服务器测试,发现效果和之前一样,事务还是没起作用。开始以为是和包扫描的位置有关,于是把扫描的位置放到文件末尾,发现还是没有起作用。最后偶然一个想法clean了下tomcat,然后重启,居然事务有效了。

总结:修改完配置文件后,clean下工程,重启加载新的配置文件。OK,问题解决。



2、如果按照你的步骤设置为ID为null的话,那么就需要捕获mybatis抛出的异常,然后在catch语句中抛出一个Exception,这个时候Spring容器的事务管理就会起作用,会回滚事务。

3、如果用mysql数据库,数据库表你如果是自动建表,那么就需要把建表的Engine设置为InnoDB格式,自动建表的格式为:MyISAM,这中格式的是不支持事务管理的。



总结下:
Spring在使用ContextLoadListener加载applicationContext.xml或其他名称的xml文件时,能进行数据源和相关事务注解的检查,启动事务特性。若在isap-servlet.xml文件中加载是,仅作为普通bean定义加载。所以一个良好的习惯就是,分层配置相关的bean。applicationContext.xml中配置数据库相关的bean(dao、service等),
isap-servlet中配置mvc相关的bean(controller等)。

转自:http://blog.csdn.net/walkerjong/article/details/7839002
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: