保存点(savepoint)¶
保存点(Savepoint)提供了对事务更小粒度的控制方法,它代表一个逻辑事务点。在自动提交模式下,用户是不允许设置保存点的,神通数据库 JDBC驱动程序将会抛出异常。在非自动提交模式下,一个事务中可以设置多个保存点,这样在回滚的时候,可以回滚到指定的保存点,从事务开始到该保存点之间的操作依然有效。这就为事务处理提供了更多的灵活性。
保存点分为命名的和未命名的两种。未命名的用系统分配的 ID作为标识。下面的例子演示了保存点的使用:
package com.sun.cts.tests.jdbc.help_doc.shi_wu;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Properties;
import org.junit.Test;
import com.sun.cts.tests.jdbc.help_doc.ru_men.JDBCTest;
public class SavePointTest {
private Connection con;
private Statement stmt;
public String DBUSER = "";
public String DBPASSWD = "";
public String DBURL = "";
public String DBDRIVER = "";
public void init() {
Properties prop = new Properties();
try {
FileInputStream in = new FileInputStream(
"." + File.separator + "testFile" + File.separator + "cts_env.properties");
prop.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
//从配置文件读取
DBUSER = prop.getProperty("DBUSER");
DBPASSWD = prop.getProperty("DBPASSWD");
DBURL = prop.getProperty("DBURL");
DBDRIVER = prop.getProperty("DBDRIVER");
try {
Class.forName(DBDRIVER);
con = DriverManager.getConnection(DBURL, DBUSER, DBPASSWD);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void execute() {
init();
try {
Statement stmt = con.createStatement();
String sql;
// 创建表
sql = "CREATE TABLE TEMP"
+ "(id INT not NULL,name varchar(255),PRIMARY KEY ( id ))";
stmt.executeUpdate(sql);
// 插入数据
con.setAutoCommit(false);
sql = "INSERT INTO TEMP VALUES(1,'shentong1')";
int rows = stmt.executeUpdate(sql);
// 设置保存点
Savepoint sp1 = con.setSavepoint("SAVEPOINT_1");
sql = "INSERT INTO TEMP VALUES (2,'shentong2')";
rows = stmt.executeUpdate(sql);
con.rollback(sp1);
con.commit();
// 查询数据
sql = "SELECT COUNT(*) FROM TEMP";
ResultSet rs = stmt.executeQuery(sql);
rs.next();
assertEquals(1, rs.getInt(1));
// 删除表
sql="DROP TABLE TEMP ";
stmt.executeUpdate(sql);
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
fail(e.getMessage());
}
}
public static void main(String[] args) {
new SavePointTest().execute();;
}
}
这样,数据库中只是增加了第一次插入的那条记录而已。这里要提请注意,在使用Savepoint之前,一定要把当前连接设置为非自动提交模式。
用户也可以调用Connection.releaseSavepoint()方法来释放设置过的保存点。一旦释放,保存点将立即变为无效,再试图调用Connection.rollback方法来引用这个保存点将导致SQLException被抛出。当全事务回滚之后,在事务中设置的所有保存点都变无效,试图引用也会导致异常。这里要注意另外一种情况,比如按顺序设置了保存点sp1,sp2,sp3,那么当用户回滚到sp2时,或将sp2释放掉,那么sp3保存点将不复存在,对sp3的释放或回滚操作将导致神通数据库 JDBC驱动程序抛出异常。