一、JDBC事务
(1)事务是作为单个逻辑工作单元执行的一系列操作。
(2)事务维护了数据的完整性、正确语义、持久性。事务中的所有SQL语句必须被成功执行,则事务才会对数据库产生持久性的影响,
如果事务中的第n条语句执行出错,表示事务运行失败,则前面的n-1条语句对数据库产生的影响可以撤销(回滚)到事务执行前的初
始状态或出错点之前的某个正确状态。
(3)JDBC在默认情况下,使用事务自动提交模式,它将接收到的每一条SQL操作当作一个事务提交给数据库服务器处理。
如果要启动手动事务模式,程序的基本结构如下:
二.JDBC事务回滚方式
JDBC事务回滚主要有两种方式:
(1)一种是回滚所有事务,恢复到事务的初始状态,直接调用Connection中的rollback()方法实现。
(2)另一种是回滚部分事务,要事先要定义保存点,发生异常时回滚到指定的保存点处。定义保存点的方法如下:
Savepoint save3 = con.setSavepoint();
三.实例分析
(1)用JDBC的手动事务处理给pubs数据库的authors作者表添加两条新记录,第一条记录的信息是正确的,第二条记录的作者编号是错误的,
分别用回滚全部事务和回滚部分事务处理异常。操作步骤如下:
第一种:回滚全部事务。
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<body>
<%
Connection con=null;
PreparedStatement st =null;
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url="jdbc:sqlserver://localhost:1433;databaseName=pubs;user=sa;password=";
con = DriverManager.getConnection(url);
String sql="insert into authors (au_id,au_lname,au_fname,phone,contract) values (?,?,?,?,?)";
st=con.prepareStatement(sql);
con.setAutoCommit(false); //关闭JDBC的自动失误提交功能
st.setString(1,"333-33-4455");
st.setString(2,"Tomcat");
st.setString(3,"Apache");
st.setString(4,"111 222-3333");
st.setInt(5,1);
st.executeUpdate();
st.setString(1,"2A2-33-4455");
st.setString(2,"Rose");
st.setString(3,"Bill");
st.setString(4,"333 222-3333");
st.setInt(5,1);
st.executeUpdate();
con.commit(); //提交事务
out.println("成功加入记录,请用查询分析器验证");
}
catch(Exception e)
{
out.println("出错:"+e);
out.println("<br>回滚全部事务");
con.rollback(); //回滚所有的事务
}
finally
{
if(st != null )
{st.close();}
if(con != null )
{
con.setAutoCommit(true);
con.close();
}
}
%>
</body>
</html>
第二种:回滚部分事务。
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<%@page import="javax.sql.*"%>
<body>
<%
Connection con=null;
PreparedStatement st =null;
int counter=0; //定义一个计数器 用于识别应该会滚到哪一个保存点
Savepoint p=null,p0=null,p1=null;
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url="jdbc:sqlserver://localhost:1433;databaseName=pubs;user=sa;password=";
con = DriverManager.getConnection(url);
String sql="insert into authors (au_id,au_lname,au_fname,phone,contract) values (?,?,?,?,?)";
st=con.prepareStatement(sql);
con.setAutoCommit(false);
p0=con.setSavepoint("1"); //保存断点
counter=1; //将断点标记为1
st.setString(1,"333-33-4455");
st.setString(2,"Tomcat");
st.setString(3,"Apache");
st.setString(4,"111 222-3333");
st.setInt(5,1);
st.executeUpdate();
p1=con.setSavepoint("2");
counter=2;
st.setString(1,"2A2-33-4455");
st.setString(2,"Rose");
st.setString(3,"Bill");
st.setString(4,"333 222-3333");
st.setInt(5,1);
st.executeUpdate();
con.commit();
out.println("成功加入记录,请用查询分析器验证");
}
catch(SQLException e)
{
out.println("出错:"+e);
out.println("<br>回滚部分事务,请用查询分析器验证");
switch(counter) //根据标示识别断点
{
case 1:
con.rollback(p0);
break;
case 2: con.rollback(p1);
break;
default:con.rollback();
}
}
finally
{
if(st != null )
{st.close();}
if(con != null )
{
con.setAutoCommit(true);
con.close();
}
}
%>
</body>
</html>