我是Spring和使用Spring jdbc开发示例程序的新手。这是为了检查spring @Trsactional如何工作并在有异常的情况下将更改回滚到Db。
但我无法做到这一点。通过我在其中一个数据库更新中引发异常,它仍然将数据插入数据库而不是回滚。
我知道某个地方我犯了错误但却无法理解。不确定这是否是正确的方法。
我在做什么: -
在主要的methis中我调用了Global类的加载方法(将jdbcTemplate作为satic成员,因为我将这个jdbcTemplate用于所有其他类)
全局类加载方法将使用ApplicationContext启动bean。
在main方法中创建Dbclass实例并将jdbcTemplate作为参数发送。
4.创建一些示例数据并调用executeDb方法。
5.execute DB方法将创建其他Dbclasss的实例并设置之前我在main方法中使用bean初始化的jdbcTemplate(我对每个操作都有单独的类 - 比如createuser,UpdataBalance等)
编辑 - 删除所有try-catch
数据库操作代码: -
@Transactional(rollbackFor={Exception.class})
public void executeDB(int count) throws Exception
{
CreateAccount newacc = new CreateAccount(jdbcTemplate);
CreateUser newusr = new CreateUser(jdbcTemplate);
//BalanceUpdate newbal = new BalanceUpdate(jdbcTemplate);
newacc.addList(acclist);
newusr.addToList(usrlist);
//newbal.addList(ballist);
newusr.execute(); // insert data to db
newacc.addAccount(); // insert data to db
//newbal.addBalance(); // insert data to db
newacc.getAccList().clear();
newusr.getUserList().clear();
//newbal.getBalanceList().clear();
if(count == 5000)
{
Thread.sleep(1000);
throw new Exception("Rollback");
}
count += 1000;
//throw new Exception();
}
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-xml -->
<context:component-scan base-package="com.example"></context:component-scan>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="username" value="system"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="startit" class="com.example.springtransaction.GlobalClass">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="dbupdate" class="com.example.springtransaction.DbUpdate">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
答案 0 :(得分:2)
您需要从方法中抛出异常,而不是在catch块中以静默方式将其记录下来。
对于已检查的例外,您需要使用@Transactional(rollbackFor = {Exception.class})
。
http://www.logicbig.com/tutorials/spring-framework/spring-data-access-with-jdbc/transactional-roll-back/
https://www.catalysts.cc/en/wissenswertes/spring-transactional-rollback-on-checked-exceptions/
答案 1 :(得分:0)
您应该删除try-catch并定义该方法抛出异常。像这样的东西
@Transactional(rollbackFor={Exception.class})
public void executeDB() throws Exception
{
if(usrlist.size() >= 5)
{
CreateAccount newacc = new CreateAccount(jdbcTemplate);
CreateUser newusr = new CreateUser(jdbcTemplate);
BalanceUpdate newbal = new BalanceUpdate(jdbcTemplate);
newacc.addList(acclist);
newusr.addToList(usrlist);
newbal.addList(ballist);
newusr.execute(); // insert data to db
newacc.addAccount(); // insert data to db
newbal.addBalance(); // insert data to db - raise exception here
}
}
<强>更新强>
包含executeDB()方法的类应该是@Component并在主类中注入该组件。 不要自己创建一个新的Dbclass()实例。
在高级别中,原因是Spring在注入声明 @Transactional 的类时会创建代理类。 您可以在此处详细了解Aspect-Oriented Programming。