引言
在项目中对数据库操作的时候保证事务的完整性是非常重要的,尤其是一个功能中需要对数据库多次操作的时候更是需要小心,其实简单的说:只要保证多次操作使用一个Connection就可以使他们在一个事务中,但是数据库jdbc默认在执行完executeQuery、executeUpdate等方法以后会自动提交事务,这样我们多次操作的时候就不能保证事务的完整性,所以需要我们手动控制事务的提交和回滚操作,下面提供一个帮助类。
package com.bjpowernode.drp.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * * @author zhenghao * */ public class DbUtil { public static Connection getConnection(){ /*Connection conn=null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); String url="jdbc:oracle:thin:@127.0.0.1:1521:databaseName"; String username="userName"; String password="password"; try { conn=DriverManager.getConnection(url, username, password); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn;*/ Connection conn=null; try { JdbcConfig jdbcConfig=XmlConfigReader.getInstance().getJdbcConfig(); Class.forName(jdbcConfig.getDriverName()); try { conn=DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUserName(), jdbcConfig.getPassword()); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } public static void close(Connection conn){ if (conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Statement statement){ if (statement!=null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(ResultSet rs) { if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void beginTransaction(Connection conn){ if (conn!=null) { try { if(conn.getAutoCommit()){ conn.setAutoCommit(false); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void commitTransaction(Connection conn){ try { if(conn!=null){ if (!conn.getAutoCommit()) { conn.commit(); } } } catch (Exception e) { // TODO: handle exception } } public static void rollbackTransaction (Connection conn) { try { if(conn!=null){ if (!conn.getAutoCommit()) { conn.rollback(); } } } catch (Exception e) { // TODO: handle exception } } public static void resetTransaction(Connection conn){ try { if(conn!=null){ if (conn.getAutoCommit()) { conn.setAutoCommit(false); }else{ conn.setAutoCommit(true); } } } catch (Exception e) { // TODO: handle exception } } }
上面的工具类中提供了数据库的连接操作;手动开启事务、提交事务、事务回滚、恢复事务状态;关闭Connection ;关闭Statement;关闭ResultSet等等操作,这样在和数据库打交道的时候会方便很多。
手动控制事务示例演示
当我们添加一个节点以后,需要判断这个节点是不是叶子(是有有子节点)而改变is_leaf这个字段的值;
public void addClientOrRegion(Client clientOrRegion) { StringBuffer sbSql = new StringBuffer(); sbSql.append("insert into t_client ( ") .append("id, pid, client_level_id, ") .append("name, client_id, bank_acct_no, ") .append("contact_tel, address, zip_code, ") .append("is_leaf, is_client) ") .append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); Connection conn = null; PreparedStatement pstmt = null; try { conn = DbUtil.getConnection(); pstmt = conn.prepareStatement(sbSql.toString()); <strong><span style="color:#ff0000;">DbUtil.beginTransaction(conn);</span></strong> // 根据表明获得id,利用id生成器 pstmt.setInt(1, IdGenerator.generate("t_client")); pstmt.setInt(2, clientOrRegion.getPid()); pstmt.setString(3, clientOrRegion.getClientLevel().getId()); pstmt.setString(4, clientOrRegion.getName()); pstmt.setString(5, clientOrRegion.getClientId()); pstmt.setString(6, clientOrRegion.getBankAcctNo()); pstmt.setString(7, clientOrRegion.getContactTel()); pstmt.setString(8, clientOrRegion.getAddress()); pstmt.setString(9, clientOrRegion.getZipCode()); pstmt.setString(10, clientOrRegion.getIsLeaf()); pstmt.setString(11, clientOrRegion.getIsClient()); pstmt.executeQuery(); // 根据id查询分销商或者区域,确定是否为叶子 Client client = findClientOrRegionById(clientOrRegion.getPid()); if (Constants.YES.equals(client.getIsLeaf())) { // 如果非叶子 应该改为叶子 modifyIsLeafField(conn, clientOrRegion.getPid(), Constants.NO); } <strong><span style="color:#ff0000;">DbUtil.commitTransaction(conn);</span></strong> } catch (Exception e) { // TODO: handle exception e.printStackTrace(); <strong><span style="color:#ff0000;">DbUtil.rollbackTransaction(conn);</span></strong> } finally { DbUtil.close(pstmt); <strong><span style="color:#ff0000;">DbUtil.resetTransaction(conn);</span></strong> DbUtil.close(conn); } }
当我们得到connection以后,调用方法来设置事务的提交为手动提交,这样当我们将两步操作都完成以后自己手动提交,如果遇到错误以后调用方法回滚事务,这样我们就可以事务的完整性。在最后释放资源的时候不要忘记恢复事务的提交状态
小结
事务在数据库中是非常重要的,尤其是项目比较大的时候,如果不能保证事务会给我们带来很大的麻烦有时候甚至是灾难。