spring aop事务为什么不回滚呢?
大家帮我看下,太纠结了。数据库是oracle 10g 设置了回滚事务,就是不回滚,每次都插入了数据。
- XML code
<!-- spring2.0的配置方式 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- <tx:method name="add*" propagation="REQUIRED" /> --> <tx:method name="mod*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" rollback-for="Exception,RuntimeException,SQLException" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <!-- Spring AOP config --> <aop:config proxy-target-class="true"> <!-- 切入点 --> <aop:pointcut id="servicesPointcut" expression="execution(* com.zyujie.service..*Impl.*(..))" /> <!-- <aop:pointcut id="daoPointcut" expression="execution(* com.zyujie.dao..*.*(..))" /> --> <!-- 运行拦截 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="servicesPointcut" /> <!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="daoPointcut" /> --> </aop:config>
- Java code
/* * 添加用户,为了测试是否开启事务。DAO层的方法 */ public int addUser(SysUser user) { logger.debug("开始执行添加用户的操作......"); Connection con = ConnectionFactory.getConnection(); String sql = "INSERT INTO USER_INFO VALUES (?,?,?,?,?,?,?,?,sysdate)"; int result = 0; PreparedStatement ps = null; try { // con.setAutoCommit(false); ps = con.prepareStatement(sql); for (int i = 0; i < 1000; i++) { String temps = i + "user"; if (i == 600) { temps = null; } ps.setString(1, temps); ps.setString(2, "test"); ps.setString(3, "99"); ps.setString(4, "测试地市"); ps.setString(5, "888"); ps.setString(6, "测试部门"); ps.setString(7, "888888"); ps.setString(8, "2"); // ps.setString(9, ""); result += ps.executeUpdate(); //有人说是这里本身就已经提交了,但是还是问问大家。 } // con.commit(); } catch (Exception e) { logger.debug("添加用户事务回滚了......"); // throw new RuntimeException("error"); // 抛出异常,测试回滚 throw new RuntimeException(); // 抛出异常,测试回滚 } finally { try { if (ps != null) { ps.close(); } if (con != null) { con.close(); } } catch (SQLException e) { // e.printStackTrace(); // throw new RuntimeException(); // 抛出异常,测试回滚 } } return result; }- Java code
/* * 添加用户,为了测试是否开启事务。Service层的接口实现类,方法 */ public int addUser(SysUser user) { return sysUserDAO.addUser(user); }
[解决办法]
兄弟,看看你数据库的存储引擎是不是支不支持事务处理等高级处理,如果不支持要换成支持事务的存储引擎
[解决办法]
<tx:method name="mod*" propagation="REQUIRED" />
这里是不是写错了,, <tx:method name="add*" propagation="REQUIRED" /> 试试..
[解决办法]
网上资料多!找个模板看看!
[解决办法]
楼主你在DAO怎样把异常抛出给Spring的,你都说能成功插入,到底catch中的
throw new RuntimeException(); // 抛出异常,测试回滚
执行没有呢?
你在
result += ps.executeUpdate(); //有人说是这里本身就已经提交了,但是还是问问大家。
后加上
throw new RuntimeException(); // 抛出异常,测试回滚
测试下;
[解决办法]
ConnectionFactory 是怎么写的,如果你的ConnectionFactory跟spring毫无关系,spring又怎么能管理你的事务
[解决办法]
connectionfactory很重要,能否把代码拿上来看看?
因为connectionfactory如果用的是jdbc的和spring无关,只是从SPRING拿DATASOURCE的话,JDBC默认的setAutoCommit为(true)。
这也就是为什么你在一条executeupdate后抛出了一个exception后数据任能插入
[解决办法]
你这样写的话完全脱离了spring事务环境。
获取getConnection要使用spring提供的方法org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSource dataSource)方法,它返回与spring事务环境中使用的connection对象。
另外你的getConnection方法完全无需同步
[解决办法]
[解决办法]
如果,楼主一定要用JDBC CONNECTION,并且支持Service层抛错,自动回滚,应该用jdbctemplate,这样,你的connectionfactory类都不需要用了,下面给出例子:
public class PriceCenterDaoImp extends SimpleJdbcDaoSupport implements IPriceCenterDao {
private Map<String, String> sqls;
@SuppressWarnings("unchecked")
public List<PriceCenter> getPriceCodeList() throws Exception {
// TODO Auto-generated method stub
return this.getJdbcTemplate().query(sqls.get("getPriceCodeList"), RowMapperUtil.getPriceCenterRowMapper());
}
public void setSqls(Map<String, String> sqls) {
this.sqls = sqls;
}
}
注意:extends SimpleJdbcDaoSupport implements IPriceCenterDao
该DAO如果是extend SimpleJdbcDaoSupport的话,需要用spring为其注入一个datasource,如下:
<?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="priceCenterDao" class="com.ccc.batch.job.dao.impl.PriceCenterDaoImp">
<property name="dataSource" ref="dataSourceLocal" />
- <property name="sqls">
- <map>
- <entry key="getPriceCodeList">
<value>SELECT PRICE_CENTER_CODE, PRICE_TABLE_NAME FROM T_PRICE_CENTER WHERE VALID_FLAG = 'Y'</value>
</entry>
</map>
</property>
</bean>
</beans>
然后,把这个dao套到service里,你的service再throw出来任何exception,就能达到你的效果了。
结论:
自己用datasource造出的jdbc connection的事务,必须自己手动控制,用不了SPRING的AOP机制。
如果要用SPRING的AOP机制,就要用SimpleJdbcDaoSupport,HIBERNATE也是同理
[解决办法]
[解决办法]
再给楼主一个例子帮助楼主理解:
<bean id="fxRateDarDao" class="x.batch.job.fxRate.FxRateDarImpl">
<property name="dataSource" ref="dataSourceDAR" />
- <property name="sqls">
- <map>
- <entry key="delSql">
<value>delete from TDAFRGN_XCHG_RT where datediff(d,EFF_DT,?)=0</value>
</entry>
- <entry key="insSql">
<value>INSERT INTO TDAFRGN_XCHG_RT( BASE_CUR_CD, TGT_CUR_CD,EFF_DT,XCHG_RT,MKT_ID) values(:baseCurrencyCode,:targetCurrencyCode,:effectiveDate, :currencyConversionRate,:marketId)</value>
</entry>
</map>
</property>
</bean>
package x.batch.job.fxRate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
public class FxRateDarImpl extends SimpleJdbcDaoSupport implements FxRateDarDAO {
private Logger log = Logger.getLogger(this.getClass());
private Map sqls;
public void setSqls(Map sqls) {
this.sqls = sqls;
}
public void deleteFxRate(Date date) {
try {
this.getSimpleJdbcTemplate().update((String) sqls.get("delSql"), date);
} catch (Exception e) {
log.error("delete fxRate error:" + e.getMessage(), e);
return;
}
}
public void insertFxRate(List fxRateList) {
try {
for (Object fxRate : fxRateList) {
this.getSimpleJdbcTemplate().update((String) sqls.get("insSql"),
new BeanPropertySqlParameterSource(fxRate));
}
} catch (Exception e) {
log.error("insert fxRate error:" + e.getMessage(), e);
return;
}
}
}