在事务处理的过程中,我们可能并不需要回滚所有的内容,而只是需要回滚其中一部分,这就需要设立事务的保存点作为标志。
具体代码如下(测试成功):
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import org.junit.Test;
/**
* 测试JDBC事务
*/
public class SavePointTest {
/**
* 测试事务
* @throws SQLException
*/
@Test
public void testSavePoint() throws SQLException {
savePointTest();
}
/**
* 测试事务
* @throws SQLException
*/
static void savePointTest() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
//声明事务的保存点
Savepoint sp = null;
try {
conn = JdbcUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
st = conn.createStatement();
String sql = "update user set money = money - 10 where id = 1";
st.executeUpdate(sql);
//设立事务保存点
sp = conn.setSavepoint();
sql = "update user set money=money-10 where id=3";
st.executeUpdate(sql);
sql = "select money from user where id=2";
rs = st.executeQuery(sql);
float money = 0.0f;
if(rs.next()) {
money = rs.getFloat("money");
}
if(money > 300) {
//假设这里抛异常,如果不加事务回滚,第一条SQL会执行成功
throw new RuntimeException("已经超过最大值!");
}
sql = "update user set money=money+10 where id=2";
st.executeUpdate(sql);
//提交事务
conn.commit();
} catch (RuntimeException e) {
if (conn != null && sp != null) {
//这里只是回滚到保存点,然后提交事务
conn.rollback(sp);
conn.commit();
}
throw e;
} catch (SQLException e) {
//如果发生SQL异常,则让事务回滚
if(conn != null) {
//回滚所有的操作
conn.rollback();
}
throw e;
} finally {
JdbcUtils.free(rs, st, conn);
}
}
}