为了账号安全,请及时绑定邮箱和手机立即绑定

springmvc + hibernate +mysql 通过@Transactional来开启事务

1.xxx-servlet.xml配置

<mvc:annotation-driven />

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

<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>

<!-- 定义数据源Bean -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<!-- 指定连接数据库的驱动 -->
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>

<!-- 指定连接数据库的URL -->
<property name="url">
<value>jdbc:mysql://localhost:3306/test</value>
</property>

<!-- 指定连接数据库的用户名 -->
<property name="username">
<value>root</value>
</property>

<!-- 指定连接数据库的密码 -->
<property name="password">
<value>111111</value>
</property>

</bean>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>

<property name="packagesToScan">
<list>
<value>net.spring.model</value>
</list>
</property>

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>

<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.format_sql">true</prop>
</props>
</property>

</bean>

<!--事务控制 -->

<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

<bean id="testDao" class="net.spring.dao.TestDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

2.调用

方法1:

TestServiceImpl

@Override
@Transactional
public void upd(){
testDao.upd(); //调用一个dao的方法

}

TestDaoImpl

@Override
public void upd(){

SQLQuery sqlQuery = this.getSession().createSQLQuery("update user set name='1111' where id='4'");

sqlQuery.executeUpdate();

throw new RuntimeException();//这里抛出异常,上面的更新操作就会回滚

//注意,如果调用的更新或者删除操作是一个存储过程,那么即便抛出了异常,也不会回滚了

//SQLQuery sqlQuery = this.getSession().createSQLQuery("{call updUser(?)}");
//sqlQuery.setInteger(0, 4);
//sqlQuery.executeUpdate();

//throw new RuntimeException();//因为调用的是一个存储过程,所以不会回滚了。

}

方法2:

TestServiceImpl

@Override
@Transactional
public void upd(){
testDao.upd(); // 第一个方法正确
testDao.upd2();//第二个方法抛异常,然后回滚
}

TestDaoImpl

@Override

public void upd(){

SQLQuery sqlQuery = this.getSession().createSQLQuery("update user set name='1111' where id='4'");
sqlQuery.executeUpdate();

}

@Override
public void upd2(){
throw new RuntimeException();
}

注:

将异常捕获,并且在catch块中不对事务做显式提交(或其他应该做的操作如关闭资源等)=生吞掉异常;
spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtime异常).
如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。
一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。

由此可以推知,在spring中如果某个业务方法被一个
try {
//bisiness logic code
} catch(Exception e) {
//handle the exception

整个包裹起来,则这个业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中抛出!全被捕获并吞掉,导致spring异常抛出触发事务回滚策略失效。

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
168
获赞与收藏
3550

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消