Java事务管理之JDBC

时间:2022-11-05 22:01:39

前言

关于Java中JDBC的一些使用可以参见:

Java 中使用JDBC连接数据库例程与注意事项


在使用JDBC的使用, 如何进行事务的管理。直接看一下代码


示例代码

/**    * @Title: JDBCTrans.java
* @Package com.oscar999.trans
* @Description:
* @author XM
* @date Feb 14, 2017 4:38:27 PM
* @version V1.0
*/
package com.oscar999.trans;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
* @author
*
*/
public class JDBCTrans {

public JDBCTrans() {

}

/**
*
* @param sHostName
* @param sPortNumber
* @param sSid
* @param userName
* @param password
* @return
* @throws SQLException
*/
public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {
Connection conn = null;
String url = getOraclURL(sHostName, sPortNumber, sSid);
conn = DriverManager.getConnection(url,userName,password);
return conn;
}

/**
*
* @param conn
* @param sql
* @throws SQLException
*/
public void add(Connection conn, String sql) throws SQLException {
Statement stmt = null;
try {
stmt = conn.createStatement();
stmt.execute(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (stmt != null)
stmt.close();
}
}

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String sHostName = "";
String sPortNumber = "";
String sSid = "";
String userName = "";
String password = "";

sHostName = "";
sPortNumber = "";
sSid = "";
userName = "";
password = "";

try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

JDBCTrans jdbcTrans = new JDBCTrans();
Connection conn = null;
try {
conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);
conn.setAutoCommit(false);// can't insert, update

//1. add SQL
String addSQL = "insert into TEST_TABLE values('name1','value1')";
jdbcTrans.add(conn,addSQL);

} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
/*if (conn != null)
{
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
}

}

private String getOraclURL(String sHostName, String sPortNumber, String sSid) {
String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;
return url;
}

}

针对以上代码, 说明如下:

以上代码有几点说明的部分:
1. conn.setAutoCommit(false) 执行之后不提交事务。
对于Select没有影响, 但对于Insert和Update的话, 没有提交数据就不会被修改
2.  conn.close(); 关闭Connection的代码有被Mark掉, 是想呈现conn.setAutoCommit(false)的效果。
原因是在 Connection Close的时候会执行一次Commit.
而如果Connection是在应用服务器中使用连接池的话, Connection就不会被Close, 也就不会执行Commit.
3. setAutoCommit(false) 用法大多数是在要执行多条语句才提交。

所以针对以上第三点, 更接近实际的状况的代码如示例代码2


示例代码2

/**    * @Title: JDBCTrans.java * @Package com.oscar999.trans * @Description:  * @author XM * @date Feb 14, 2017 4:38:27 PM * @version V1.0    */package com.oscar999.trans;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;/** * @author *  */public class JDBCTrans {public JDBCTrans() {}/** *  * @param sHostName * @param sPortNumber * @param sSid * @param userName * @param password * @return * @throws SQLException */public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {Connection conn = null;String url = getOraclURL(sHostName, sPortNumber, sSid);conn = DriverManager.getConnection(url, userName, password);return conn;}/** *  * @param conn * @param sql * @throws SQLException */public void add(Connection conn, String sql) throws SQLException {Statement stmt = null;try {stmt = conn.createStatement();stmt.execute(sql);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (stmt != null)stmt.close();}}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubString sHostName = "";String sPortNumber = "";String sSid = "";String userName = "";String password = "";sHostName = "";sPortNumber = "";sSid = "";userName = "";password = "";try {Class.forName("oracle.jdbc.driver.OracleDriver");} catch (ClassNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}JDBCTrans jdbcTrans = new JDBCTrans();Connection conn = null;try {conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);conn.setAutoCommit(false);// can't insert, update// 1. add SQL 1String addSQL = "insert into TEST_TABLE values('name1','value1')";jdbcTrans.add(conn, addSQL);//2. add SQL 2addSQL = "insert into TEST_TABLE values('name2','value2')";jdbcTrans.add(conn, addSQL);conn.commit();} catch (SQLException e) {// TODO Auto-generated catch blockif(conn!=null){                 try {                 conn.rollback();                 } catch (SQLException e1) {                     e1.printStackTrace();                 }             } e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}private String getOraclURL(String sHostName, String sPortNumber, String sSid) {String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;return url;}}

这里需要说明的是 
 conn.rollback();  


只要执行有异常,就要rollback , 这一步必不可少


如果没有在执行出现异常的时候进行回滚。如果在执行第一条语句之后出现异常,con既没有提交也没有回滚,表就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。
可能在执行con.close()的时候会释放锁,但还是如果应用服务器使用了数据库连接池,连接不会被断开。