在Spring一统天下的情况下,JDBC快没有生存余地了。不过JDBC还是Java操作数据库的基础,现在Java项目中JDBC的应用快绝迹了,有必要对JDBC的事务编程模型做个象征性的总结。
下面是示例,保证代码可以编译,但不保证能运行,呵呵。
import java.sql.*;
/**
* JDBC编程事务控制模型备忘
*
* @author : leizhimin,2008-8-21 14:48:42。<p>
*/
public class JdbcTxText {
public static void main(String[] args) {
test();
}
public static void test() {
Connection conn = null;
//定义一个回滚点
Savepoint savepoint1 = null;
try {
//获取一个数据库连接
conn = DriverManager.getConnection( "url", "user", "password");
//设置不自动提交,相当于开启了事务
conn.setAutoCommit( false);
//设置JDBC事务的级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//创建一个用于执行静态 SQL 语句并返回它所生成结果的对象
Statement stmt = conn.createStatement();
//执行连个SQL语句,在同一个事务中
stmt.executeUpdate( "insert into test values(1,'aaa')");
//定义一个回滚到(保存点)savepoint1,在事务失败的时候,可以回滚到定义的回滚点
savepoint1 = conn.setSavepoint( "insert_end");
stmt.executeUpdate( "update test set name = 'bbb' where id =1");
//提交事务
conn.commit();
} catch (SQLException e) {
try {
//当事务失败时候,回滚到(保存点)savepoint1
conn.rollback(savepoint1);
// 当本事务中的插入和更新SQL其中一个执行异常的时候,整个事务回滚
//conn.rollback();
} catch (SQLException e1) {
throw new RuntimeException( "回滚事务发生异常!", e);
}
throw new RuntimeException( "执行事务发生异常!", e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException( "关闭数据库连接发生异常!", e);
}
}
}
}
}
/**
* JDBC编程事务控制模型备忘
*
* @author : leizhimin,2008-8-21 14:48:42。<p>
*/
public class JdbcTxText {
public static void main(String[] args) {
test();
}
public static void test() {
Connection conn = null;
//定义一个回滚点
Savepoint savepoint1 = null;
try {
//获取一个数据库连接
conn = DriverManager.getConnection( "url", "user", "password");
//设置不自动提交,相当于开启了事务
conn.setAutoCommit( false);
//设置JDBC事务的级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//创建一个用于执行静态 SQL 语句并返回它所生成结果的对象
Statement stmt = conn.createStatement();
//执行连个SQL语句,在同一个事务中
stmt.executeUpdate( "insert into test values(1,'aaa')");
//定义一个回滚到(保存点)savepoint1,在事务失败的时候,可以回滚到定义的回滚点
savepoint1 = conn.setSavepoint( "insert_end");
stmt.executeUpdate( "update test set name = 'bbb' where id =1");
//提交事务
conn.commit();
} catch (SQLException e) {
try {
//当事务失败时候,回滚到(保存点)savepoint1
conn.rollback(savepoint1);
// 当本事务中的插入和更新SQL其中一个执行异常的时候,整个事务回滚
//conn.rollback();
} catch (SQLException e1) {
throw new RuntimeException( "回滚事务发生异常!", e);
}
throw new RuntimeException( "执行事务发生异常!", e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException( "关闭数据库连接发生异常!", e);
}
}
}
}
}
上面代码中:
//设置JDBC事务的级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//当事务失败时候,回滚到(保存点)savepoint1
conn.rollback(savepoint1);
conn.rollback(savepoint1);
JDBC的事务级别设置,保存点(或回滚点)的设置与数据库和JDBC的驱动的实现有关系,并非完全支持,但是不支持也不会出错。
如果要编写线程安全的JDBC DAO,则可参考如下的示例:
/**
* JDBC线程的安全控制
*
* @author : leizhimin 2008-9-11 20:55:13
*/
public class SomeOneDAO {
private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>();
public static Connection getConnection() {
Connection conn = null;
if (connThreadLocal.get() == null) {
conn = DBHelp.makeConnection();
connThreadLocal.set(conn);
} else {
conn = connThreadLocal.get();
}
return conn;
}
public Long saveSomeone(SomeOne someOne) {
Statement stmt = getConnection().createStatement();
Long id = (Long) getJDBCTemplate.getSqlMapClient.insert( "insert", someOne);
.....
return id;
}
}
* JDBC线程的安全控制
*
* @author : leizhimin 2008-9-11 20:55:13
*/
public class SomeOneDAO {
private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>();
public static Connection getConnection() {
Connection conn = null;
if (connThreadLocal.get() == null) {
conn = DBHelp.makeConnection();
connThreadLocal.set(conn);
} else {
conn = connThreadLocal.get();
}
return conn;
}
public Long saveSomeone(SomeOne someOne) {
Statement stmt = getConnection().createStatement();
Long id = (Long) getJDBCTemplate.getSqlMapClient.insert( "insert", someOne);
.....
return id;
}
}
以上的代码都是模型,并非可执行代码。。。
JTA事务
顺便说说JTA(Java Transaction API)是J2EE标准的一部分。JTA建立在JTS(Java Transaction Service)标准之上的。JTS是一个底层API共应用服务器厂商使用,而JTA是一个高层接口,供开发者使用。
既然JDBC标准已经支持了数据库事务,为什么还要一个JTA标准呢?
原因是:JDBC是一个局部事务,只能应用于当前数据库。在分布式环境下,如果事务需要跨越多个数据库,则只能使用支持分布式应用的JTA标准。
如果要使用JTA事务,则一般有多个数据库参与JTA事务,这要求数据库的JDBC驱动程序实现XAConnection和XAResource接口,只有实现了这些接口的JDBC驱动才能正确地参与JTA事务。并非所有的数据库驱动都支持JTA事务,一些高端J2EE服务器支持将普通的JDBC驱动模拟为支持XA的JDBC驱动。
一旦使用了JTA事务,则XAConnection就会自动参与JTA事务,它们不能自动提交。
对于一个数据库,就没必要使用JTA事务了,免得带来不必要的复杂性。
对于多个数据库的应用,则需要使用JTA事务。
如果为了以后的扩展,则刚开始就可以使用JTA事务。
另外,Spring已经简化了事务的管理,对于选择什么样的事务标准,已经不重要的了。Spring使用了一种抽象的事务编程模型,配合声明式事务管理,选择什么样的事务仅仅是修改下配置文件即可。
本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/94076,如需转载请自行联系原作者