上一篇(
http://blog.csdn.net/rowandjj/article/details/8973819)我们研究了JDBC中的元数据,
JDBC中的元数据分为三类,DatabaseMetaData(数据库元数据)、ParameterMetaData(参数元数据),ResultSetMetaData(结果集元数据)。具体用法请大家参照上一篇博文。
下面我们讲JDBC中的另外一个重点——事务处理。
概念:
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
事务的特性(ACID):
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
事务的特性(ACID):
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
隔离性(Isolation):事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
JDBC中的事务操作:
在JDBC的数据库操作中,一项事务是由一条或是多条表达式所组成的一个不可分割的工作单元。我们通过提交commit()或是回退rollback()来结束事务的操作。关于事务操作的方法都位于接口java.sql.Connection中。首先我们要注意,在JDBC中,事务操作默认是自动提交。也就是说,一条对数据库的更新表达式代表一项事务操作。操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回退。其次,在JDBC中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交。倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常。此时就可以在异常捕获时调用rollback()进行回退。这样做可以保持多次更新操作后,相关数据的一致性。
具体事例代码如下:
1.判断是否支持事务:
Connection conn = DriverManager.getConnection(url);
DatabaseMetaData dbmd = conn.getMetaData();
boolean temp = dbmd.supportsTransactions();//判断是否支持事务
2.判断是否是自动提交状态:
boolean flag = conn.getAutoCommit();//获取当前是否是自动提交状态
3.基本操作
try {
conn = DriverManager.getConnection(url);
conn.setAutoCommit(false); //禁止自动提交,设置回退
stmt = conn.createStatement();
stmt.executeUpdate(“update firsttable Set Name='testTransaction' Where ID = 1”); //数据库更新操作1
stmt.executeUpdate(“insert into firsttable ID = 12,Name = 'testTransaction2'”); //数据库更新操作2
conn.commit(); //事务提交
}
catch(Exception ex) {
try {
conn.rollback(); //操作不成功则回退
//rollback -> 取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。
}
catch(Exception e){
e.printStackTrace();
}
}
实现事务处理的基本流程如下:
1)判断当前使用的JDBC驱动程序和数据库是否支持事务处理;
2)在支持事务处理的前提下,取消系统自动提交模式;
3)添加需要进行的事务信息;
4)将事务处理提交到数据库;
5)在处理事务时,若某条信息发生错误,则执行事务回滚操作,并回滚到事务提交前的状态。
下面看一个综合一点的例子:
package demo;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class MyTranscationDemo
{
// 判断是否支持事务
public static boolean getTranstraction(Connection conn) throws SQLException
{
DatabaseMetaData dbmd = conn.getMetaData();
boolean flag = dbmd.supportsTransactions();
if(flag)
{
return true;
}
else
{
return false;
}
}
//开始事务
public static void startTranscation(Connection conn,String sql[])
{
PreparedStatement ps = null;
try
{
conn.setAutoCommit(false);//关闭自动提交
for(int i = 0; i < sql.length; i++)
{
ps = conn.prepareStatement(sql[i]);
ps.execute();//执行第i个sql语句
}
System.out.println("提交事务处理!");
conn.commit();//提交事务
System.out.println("事务处理结束!");
}
catch (SQLException e)
{
try
{
System.out.println("事务执行失败,进行回滚!\n");
conn.rollback();
}
catch (SQLException e2)
{
// TODO: handle exception
e2.printStackTrace();
}
e.printStackTrace();
}
finally
{
try
{
if(ps != null)
ps.close();
}
catch (SQLException ee)
{
ee.printStackTrace();
}
}
}
public static void main(String[] args)
{
Connection conn = null;
String[] sql = new String[3];
sql[0] = new String("delete from tb_9 where name='lisi'");
sql[1] = new String("update tb_9 set money= 0 where name= 'nimei'");
sql[2] = new String("insert into tb_9 values (5,'zhangsanfeng','1111-1-1',100)");
try
{
conn = JDBCUtils.getConnection();//获取连接(JDBCUtils类定义见前几篇博文)
if(getTranstraction(conn))
{
System.out.println("数据库支持事务!");
startTranscation(conn, sql);
}
else
{
System.out.println("数据库不支持事务");
}
}
catch (SQLException e)
{
// TODO: handle exception
e.printStackTrace();
}
}
}
个人疑问:
上面代码是参考网上的,笔者觉得有点问题,个人认为程序中
catch语句中的rollback操作没有意义,因为如果加入try块中的语句抛出SQL异常的话,会自动跳转到catch块中,也就是没有执行commit操作,所以加不加rollback操作 效果是一样的。个人愚见,大家有不同看法欢迎留言!
Connection类中还有一些跟事务操作相关的方法,比如setSavePoint(设置保存点),具体用法请大家查看文档,在此不再敖述。
本文到此为止,下篇文章介绍批处理相关内容。谢谢!