SSH事务不能回滚问题,求好人解答

yuandaobo 2013-03-11 09:13:43
项目结构大致分为三层。数据库访问层dao、业务处理层biz、action层
现在我将事务配置加在了biz层,当biz层里面有两个数据库操作时,其中一个会出错(故意让其出错的),但是第一个数据库操作还是成功了,没有回滚,不知道是什么原因。下面是sping里面的事务配置:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml">
</property>
</bean>

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- 配置事务特性 ,配置add、delete和update开始的方法,事务传播特性为required -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>

<!-- 配置那些类的方法进行事务管理,当前com.ilb.dao包中的子包、类中所有方法需要,还需要参考tx:advice的设置 -->
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution (* com.cloudsoar3c.biz.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>
</aop:config>

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

好人路过帮看看,谢谢
下面是部分代码:
DAO层代码:

public void add(Object ogj) throws Exception{
super.getHibernateTemplate().getSessionFactory().getCurrentSession().save(ogj);
}

biz层代码:
public TOrder addNewOrder(Integer buyCount, TClient client)throws Exception{
TServerHostLicense serverHostLicense = new TServerHostLicense();
serverHostLicense.setHostId(System.currentTimeMillis()+"");
serverHostLicense.setAddTime(new Date());
serverHostLicense.setHostName("测试主机名");
serverHostLicense.setLicenseFile("licenseFile........");
serverHostLicense.setStatus(-1);
serverHostLicense.setSupportClientCount(buyCount);
serverHostLicense.setTClient(client);
//添加主机服务器信息
//boolean addResult = this.serverHostLicenseDao.add(serverHostLicense);
this.serverHostLicenseDao.add(serverHostLicense);
TLicensePrice licensePrice = getPriceByBuyCount(buyCount);//获取单价
TOrder order = new TOrder();
//生成订单ID
String orderId = this.utilBiz.getUUID(Attribute.UUID_ORDER);
order.setOrderId("1362726845687907");//此处ID故意重复,让其出错
order.setBuyCount(buyCount);
order.setOrderTime(new Date());
order.setPreferentialPrice(0);//默认优惠价格为0
order.setPrice(licensePrice.getPrice());
order.setStatus(Attribute.ORDER_STATE_DFK);//初始化状态为待付款状态
order.setTClient(client);
order.setTServerHostLicense(serverHostLicense);
order.setTotalPrice((Integer.parseInt(licensePrice.getPrice())*buyCount+""));
this.orderDao.addOrder(order);//添加新增订单到数据库中
return order;

Action层代码:
try {
order = this.orderBiz.addNewOrder(buyCount, client);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

现在问题是TServerHostLicense serverHostLicense对象添加成功、TOrder order添加失败
...全文
532 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuandaobo 2013-03-12
  • 打赏
  • 举报
回复
引用 19 楼 XiangZhiLiu 的回复:
事物也跟数据库运行模式有关。你的代码你实在找不出问题,你可以看下是不是数据库的原因。
这位兄弟的提示很对(还有12楼兄弟),我也没看出来哪里配置有问题,并且我也没有对异常进行捕获,最后一看,我的MySql数据库表引警为MyISAM,在google一下,说这种引警不支持事务,只有InnoDB类型才支持,我修改了数据库中需要进行事务处理的表的引擎,再测试发现,事务成功回滚(心里总算是踏实了),后来我又想着试试如果我捕获异常,会不会有问题,我在DAO层和BIZ层都捕获取异常,并且捕获异常后,也没有另外处理(TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();),发现事务依然可以成功回滚、所以我认为捕获异常应该不会对事务回滚造成影响,可是在网上好多人认为有影响的,不知道是我测试哪里有问题还是怎么了,如果哪位仁兄知道,请不吝赐教、
且活且珍惜 2013-03-12
  • 打赏
  • 举报
回复
你可以自己封装个单一事物的方法,反正我真的不喜欢spring
且活且珍惜 2013-03-12
  • 打赏
  • 举报
回复
什么都配来配去很蛋疼
lvzg_005 2013-03-11
  • 打赏
  • 举报
回复
默认的配置中,spring框架的事务设施代码仅仅标记运行时非检查异常来设置回滚标记,也就是说当抛RuntimeException实例或子类时。在默认的配置中,如果检查性异常被抛出是不会引起事务回滚的。 下面的代码片段说明了怎么给应用程序指定的checked异常回滚操作 <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/> <tx:method name="*"/> </tx:attributes> </tx:advice> 同样,可以指定某种异常不用回滚 <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/> <tx:method name="*"/> </tx:attributes> </tx:advice>
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
现在如果我在biz层的方法中,直接添加一个throw new RuntimeException("");,事务就会回滚,代码如下:
public TOrder addNewOrder(Integer buyCount, TClient client){
		TServerHostLicense serverHostLicense = new TServerHostLicense();
		serverHostLicense.setHostId(System.currentTimeMillis()+"");
		serverHostLicense.setAddTime(new Date());
		serverHostLicense.setHostName("测试主机名");
		serverHostLicense.setLicenseFile("licenseFile........");
		serverHostLicense.setStatus(-1);
		serverHostLicense.setSupportClientCount(buyCount);
		serverHostLicense.setTClient(client);
		//添加主机服务器信息
		//boolean addResult = this.serverHostLicenseDao.add(serverHostLicense);
		this.serverHostLicenseDao.add(serverHostLicense);
		//TLicensePrice licensePrice = getPriceByBuyCount(buyCount);//获取单价
		TOrder order = new TOrder();
		//生成订单ID
		//String orderId = this.utilBiz.getUUID(Attribute.UUID_ORDER);
		order.setOrderId("1362726845687907");//此处ID故意重复,让其出错
		order.setBuyCount(buyCount);
		order.setOrderTime(new Date());
		order.setPreferentialPrice(0);//默认优惠价格为0
		//order.setPrice(licensePrice.getPrice());
		order.setPrice("111");
		order.setStatus(Attribute.ORDER_STATE_DFK);//初始化状态为待付款状态
		order.setTClient(client);
		order.setTServerHostLicense(serverHostLicense);
		//order.setTotalPrice((Integer.parseInt(licensePrice.getPrice())*buyCount+""));
		order.setTotalPrice("2222");
		this.orderDao.addOrder(order);//添加新增订单到数据库中
		if(1==1){
			throw new RuntimeException("");
		}
		return order;
}
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 12 楼 fangmingshijie 的回复:
不知道你用的什么数据库,mysql?看下数据库是什么引擎的?如果不是innerdb,就不能自动提交事务。在 hibernate配置文件里加上<property name="connection.autocommit">false</property>
数据库用的mysql,刚才使用命令show variables like 'table_type';查看表类型是:MyISAM 然后我添加了<property name="connection.autocommit">false</property>问题仍然存在
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 11 楼 henrylove 的回复:
<aop:pointcut id="allManagerMethod" expression="execution (* com.cloudsoar3c.biz.*.*(..))"/> 试试改成这样行不行. expression="execution (* com.cloudsoar3c.biz.*.*(..))"/> 第一个*代表的是返回值;第二个*表示的是biz……
多谢你的回复,我改了以后,还是这样,下面是我修改后的代码
<aop:pointcut id="allManagerMethod" expression="execution (* com.cloudsoar3c.biz.*.*(..))"/>
  • 打赏
  • 举报
回复
不知道你用的什么数据库,mysql?看下数据库是什么引擎的?如果不是innerdb,就不能自动提交事务。在 hibernate配置文件里加上<property name="connection.autocommit">false</property>
henrylove 2013-03-11
  • 打赏
  • 举报
回复
<aop:pointcut id="allManagerMethod" expression="execution (* com.cloudsoar3c.biz.*.*(..))"/> 试试改成这样行不行. expression="execution (* com.cloudsoar3c.biz.*.*(..))"/> 第一个*代表的是返回值;第二个*表示的是biz下面的子包;第三个*表示的是方法名称;(..)表示的是方法参数. 试试看!!
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 9 楼 dracularking 的回复:
引用 8 楼 yuandaobo 的回复:引用 7 楼 shxt_xiaozhi 的回复:看看前后是否是一个事物,是的话在catch里写代码会滚吧 回滚代码是在biz层写呢,还是在Action层?还请明示 哪个层应该没关系的,spring界定事务属性与哪个层无关吧 就看事务边界界定了没,现在通过add*,还有按理应该自动回滚的吧?没有自动回滚肯定有原因存在,找到……
多谢你的回复,我上面有关于事务部分的配置,我看不出来哪里有问题,能不能帮我看看,谢谢了,这问题卡了一天了
dracularking 2013-03-11
  • 打赏
  • 举报
回复
引用 8 楼 yuandaobo 的回复:
引用 7 楼 shxt_xiaozhi 的回复:看看前后是否是一个事物,是的话在catch里写代码会滚吧 回滚代码是在biz层写呢,还是在Action层?还请明示
哪个层应该没关系的,spring界定事务属性与哪个层无关吧 就看事务边界界定了没,现在通过add*,还有按理应该自动回滚的吧?没有自动回滚肯定有原因存在,找到原因而不是直接手动回滚
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 7 楼 shxt_xiaozhi 的回复:
看看前后是否是一个事物,是的话在catch里写代码会滚吧
回滚代码是在biz层写呢,还是在Action层?还请明示
且活且珍惜 2013-03-11
  • 打赏
  • 举报
回复
看看前后是否是一个事物,是的话在catch里写代码会滚吧
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 5 楼 yyw6637 的回复:
你dao层有没有捕获异常?
dao没有捕获,直接抛出Exception的,dao层代码如下
public void add(Object ogj) throws Exception{
		super.getHibernateTemplate().getSessionFactory().getCurrentSession().save(ogj);
	}
yyw6637 2013-03-11
  • 打赏
  • 举报
回复
你dao层有没有捕获异常?
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 2 楼 yyw6637 的回复:
你捕获了异常,所有回滚不了的,要么去掉try,要么在catch里加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly ;
我加了以后,还是一样,还请指教,下面是Action修改后的代码:
			try {
				order = this.orderBiz.addNewOrder(buyCount, client);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
				e.printStackTrace();
			}
yuandaobo 2013-03-11
  • 打赏
  • 举报
回复
引用 1 楼 fangmingshijie 的回复:
Java code?1234567try { order = this.orderBiz.addNewOrder(buyCount, client); } catch (Exception e) { // TODO Auto-generated catch block//这里怎么没有实物回滚……
这个代码是Action里面的,需要在这里加吗?还有xxx能不能说下是什么、以前没有手动写过事务回滚
yyw6637 2013-03-11
  • 打赏
  • 举报
回复
你捕获了异常,所有回滚不了的,要么去掉try,要么在catch里加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly ;
  • 打赏
  • 举报
回复

try {
                order = this.orderBiz.addNewOrder(buyCount, client);
            } catch (Exception e) {
                // TODO Auto-generated catch block
//这里怎么没有实物回滚语句呢?XXX.rollback();
                e.printStackTrace();
            }


bbaass_2009 2013-03-11
  • 打赏
  • 举报
回复
按照我老大的说法,你配置语句里面tx:annotation-driven 这句话,不用,这是生命用注解吧,你删了试试.. 如果你切入点没配错的话,照理说dao,service一直上抛应该是可以回滚的...我也不懂,在学..
加载更多回复(4)

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧