flyFish's recorder.

JDBC的事务控制

2018/06/27 Share

JDBC

控制事务的方法:
在connection类中提供了3个控制事务的方法:

  • setAutoCommit(Boolean autoCommit):设置是否自动提交事务;
  • commit();提交事务;
  • rollback();撤消事务;

在jdbc api中,默认的情况为自动提交事务,也就是说,每一条对数据库的更新的sql语句代表一项事务,操作成功后,系统自动调用commit()来提交,否则将调用rollback()来撤消事务(和第二篇数据库的事务控制一致)。

所以我们在java中控制事务的思路

  • 设置事务不自动提交
  • 执行代码
  • 全部成功,commit
  • 有错,rollback

以Oracle为例,演示事务控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 1. 转账,使用事务
public void trans1() {

String sql_zs = "UPDATE t_user SET money=money-1000 WHERE USERName='张三'";
String sql_ls = "UPDATE1 t_user SET money=money+1000 WHERE USERName='李四'";

try {
con = JdbcUtil.getConnection(); // 默认开启的隐式事务
// 一、设置事务为手动提交
con.setAutoCommit(false);

/*** 第一次执行SQL ***/
pstmt = con.prepareStatement(sql_zs);
pstmt.executeUpdate();

/*** 第二次执行SQL ***/
pstmt = con.prepareStatement(sql_ls);
pstmt.executeUpdate();
// 三、所有的操作执行成功, 提交事务
con.commit();
} catch (Exception e) {
// 二、 出现异常,需要回滚事务
con.rollback();
e.printStackTrace();
} finally {
try {
JdbcUtil.close(con, pstmt, null);
} catch (SQLException e) {
e.printStackTrace();
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 2. 转账,使用事务, 回滚到指定的代码段
@Test
public void trans2() {
// 定义个标记
Savepoint sp = null;

// 第一次转账
String sql_zs1 = "UPDATE t_user SET money=money-1000 WHERE USERName='张三'";
String sql_ls1 = "UPDATE t_user SET money=money+1000 WHERE USERName='李四'";

// 第二次转账
String sql_zs2 = "UPDATE t_user SET money=money-500 WHERE USERName='张三'";
String sql_ls2 = "UPDATE1 t_user SET money=money+500 WHERE USERName='李四'";

try {
con = JdbcUtil.getConnection(); // 默认开启的隐式事务
con.setAutoCommit(false); // 设置事务手动提交

//设置事务隔离级别
con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//获得当前数据库的事务隔离级别
System.out.println("事务隔离级别:"+ con.getTransactionIsolation());

/*** 第一次转账 ***/
pstmt = con.prepareStatement(sql_zs1);
pstmt.executeUpdate();
pstmt = con.prepareStatement(sql_ls1);
pstmt.executeUpdate();

// 回滚到这个位置
sp = con.setSavepoint();


/*** 第二次转账 ***/
pstmt = con.prepareStatement(sql_zs2);
pstmt.executeUpdate();
pstmt = con.prepareStatement(sql_ls2);
pstmt.executeUpdate();

// 提交
con.commit();
} catch (Exception e) {
// 回滚 (回滚到指定的代码段)
con.rollback(sp);
e.printStackTrace();
} finally {
JdbcUtil.close(con, pstmt, null);
}
}

比较简单,不多说。贴下JdbcUtilproperties的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* jdbc工具类
* @author flyfish
*
*/
public class JdbcUtil {
private static String url = null;
private static String user = null;
private static String password = null;
private static String driverClass = null;

/**
* 静态代码块中(只加载一次)
*/
static{
try {
//读取db.properties文件
Properties props = new Properties();
/**
* . 代表java命令运行的目录
* 在java项目下,. java命令的运行目录从项目的根目录开始
* 在web项目下, . java命令的运行目录从tomcat/bin目录开始
* 所以不能使用点.
*/
//FileInputStream in = new FileInputStream("./src/db.properties");//D:\javaee\myeclipse10.0\workspace\day16_jdbc_1\src\db.properties

/**s
* 使用类路径的读取方式
* / : 斜杠表示classpath的根目录
* 在java项目下,classpath的根目录从bin目录开始
* 在web项目下,classpath的根目录从WEB-INF/classes目录开始
*/
InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");

//加载文件
props.load(in);
//读取信息
url = props.getProperty("url");
user = props.getProperty("user");
password = props.getProperty("password");
driverClass = props.getProperty("driverClass");


//注册驱动程序
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
System.out.println("驱程程序注册出错");
}
}

/**
* 抽取获取连接对象的方法
*/
public static Connection getConnection(){
try {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}


/**
* 释放资源的方法
*/
public static void close(Connection conn,Statement stmt){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

public static void close(Connection conn,Statement stmt,ResultSet rs){
if(rs!=null)
try {
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
@Test
public void test1(){
System.out.println(getConnection());
}
}
1
2
3
4
5
url=jdbc:oracle:thin:@localhost:1521:XE
user=wyj
password=wyj
driverClass=oracle.jdbc.driver.OracleDriver
#这里的数据库配置根据实际数据库选择。
CATALOG
  1. 1. JDBC