- 浏览: 332301 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
327764984:
CommonSql里不知道把PreparedStatment和 ...
Connection.setAutoCommit使用的注意事项 -
netwelfare:
文章讲解的不详细啊,很多东西没有讲解出来。看到这篇文章讲解的挺 ...
java字符串的拆分 lang.String.split -
iceage1980:
博主你好 我用了你这个代码 为什么总是在 if (this. ...
MD5 码 校 验 -
wisdomtl:
最后一段代码有写小的错误最后一个具体工厂的实现应该返回Cowb ...
JAVA设计模式之工厂模式 -
jateide:
网上随便转载的东西,自己都没有经过使用,好意思发出来,而且还不 ...
正则表达式中后向引用、零宽断言、负向零宽断言的解释用法
setAutoCommit总的来说就是保持数据的完整性,一个系统的更新操作可能要涉及多张表,需多个SQL语句进行操作 循环里连续的进行插入操作,如果你在开始时设置了:conn.setAutoCommit(false); 最后才进行conn.commit(),这样你即使插入的时候报错,修改的内容也不会提交到数据库, 而如果你没有手动的进行setAutoCommit(false); 出错时就会造成,前几条插入,后几条没有 会形成脏数据~~ setAutoCommit(false)的误用 (设定setAutoCommit(false)没有在catch中进行Connection的rollBack操作,操作的表就会被锁住,造成数据库死锁): 误用Connection.setAutoCommit导致的数据库死锁问题。 系统在发布到用户的的服务器了,运行一段时间偶尔出现某些功能不能正常运行,甚至不能自动恢复,严重导致服务器当机,表现为服务器不响应用户的请求,数据库有大量的锁。在服务器重启后才能恢复正常。今天通遍的查看了一下代码,初步分析了原因,记录了下来,跟大家交流交流。 先看下面一段有问题的代码: 1 Connection con = null; 2 try{ 3 con = getConnection(); 4 con.setAutoCommit(false); /* 5 * update USER set name=’winson’ where id=’000001’; */ 6 con.commit(); 7 }finally{ 8 if(con!=null){ 9 try { 10 con.close(); 11 } catch (SQLException e) { 12 e.printStackTrace(); 13 } } } 分析:问题就出现在第4行,写代码的人把数据库连接con 设置成非自动提交,但没有在执行出现异常的时候进行回滚。如果在执行第5行的时候出现异常,con既没有提交也没有回滚,表USER就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。有人会质疑,在执行con.close()的时候不会释放锁吗?因为如果应用服务器使用了数据库连接池,连接不会被断开。 附:在oracle上查看锁的方法:select * from v$lock_object或者select * from v$lock. JDBC的api文档是这样对setAutoCommit方法解释的: Sets the connection's auto-commit mode to enableAutoCommit. Newly created Connection objects are in auto-commit mode by default, which means that individual SQL statements are committed automatically when the statement is completed. To be able to group SQL statements into transactions and commit them or roll them back as a unit, auto-commit must be disabled by calling the method setAutoCommit with false as its argument. When auto-commit is disabled, the user must call either the commit or rollback method explicitly to end a transaction.(一定不能大意哦,如果设置成非自动提交,在最后一定要调用commit或者rollback方法) The commit occurs when the statement completes or the next execute occurs, whichever comes first. In the case of statements returning a ResultSet object, the statement completes when the last row of the result set has been retrieved or the ResultSet object has been closed. In advanced cases, a single statement may return multiple results as well as output parameter values. In this case, the commit may occur when all results and output parameter values have been retrieved, or the commit may occur after each result is retrieved. 参考正确的写法应该是: Connection con = null; try{ con = getConnection(); con.setAutoCommit(false); /* * do what you want here. */ con.commit(); }catch(Throwable e){ if(con!=null){ try { con.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } throw new RuntimeException(e); }finally{ if(con!=null){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } 这种疏忽很容易出现,但又导致非常严重的运行问题。所以在这里作个提醒,以后在处理外部资源的时候一定要格外小心。今天还发现代码中一些地方滥用synchronized关键字,导致系统性能受到很大的影响,处理不当跟前面提到问题一起出现,那系统就是时候over了。 另外,如果不是自己来处理事务,可能在用hibernate或者ejb等,都一定要记住在处理完之后要提交或者回滚哦。 例子: import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; /** * 用于JDBC操作数据库的公共类 */ public class CommonSql { /** 数据库连接对象 */ private Connection conn; /** 数据库操作对象 */ private PreparedStatement ps; /** 返回的数据结果集对象 */ private ResultSet rs; /** * 测试数据库连接是否成功 * @param args */ /** * 打开数据库连接并创建数据库连接对象 * @return boolean true:连接成功,false:连接失败 */ public boolean openConn() { Boolean isPassed = false; String driver = RWProperties.getProperty("driver", "com/test/config/db.properties"); String url = RWProperties.getProperty("url", "com/test/config/db.properties"); String user = RWProperties.getProperty("user", "com/test/config/db.properties"); String pwd = RWProperties.getProperty("pwd", "com/test/config/db.properties"); try { Class.forName(driver); conn = DriverManager.getConnection(url, user, pwd); isPassed = true; } catch (ClassNotFoundException e) { closeAll(); e.printStackTrace(); System.out.println("数据库连接失败!"); } catch (Exception e) { closeAll(); e.printStackTrace(); System.out.println("数据库连接失败!"); } return isPassed; } /** * 执行数据库的新增和修改语句,只操作一张表 * @param sql 要执行的SQL语句 * @return boolean true:执行成功,false:执行失败 */ /** * 执行数据库的新增和修改语句,同时操作多张表 * @param sql 要执行的SQL语句的字符串数组 * @return boolean true:执行成功,false:执行失败 */ public boolean execUpdate(String[] sql) { boolean isPassed = false; // 判断连接数据库是否成功 if (openConn()) { try { conn.setAutoCommit(false); for (int i = 0; i < sql.length; i++) { ps = conn.prepareStatement(sql[i]); ps.executeUpdate(); } conn.commit(); isPassed = true; } catch (SQLException e) { try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } for (int i = 0; i < sql.length; i++) { System.out.println("SQL:"+sql[i]); } e.printStackTrace(); } finally { closeAll(); } } else { closeAll(); for (int i = 0; i < sql.length; i++) { System.out.println(sql[i]); } System.out.println("数据库连接失败!"); } return isPassed; } /** * 执行数据库的新增和修改语句,同时操作多张表 * @param sql 要执行的SQL语句的集合 * @return boolean true:执行成功,false:执行失败 */ public boolean execUpdate(List<String> sql) { boolean isPassed = false; // 判断连接数据库是否成功 if (openConn()) { try { conn.setAutoCommit(false); for (int i = 0; i < sql.size(); i++) { ps = conn.prepareStatement(sql.get(i)); ps.executeUpdate(); } conn.commit(); isPassed = true; } catch (SQLException e) { try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } for (int i = 0; i < sql.size(); i++) { System.out.println("SQL:"+sql.get(i)); } e.printStackTrace(); } finally { closeAll(); } } else { closeAll(); for (int i = 0; i < sql.size(); i++) { System.out.println(sql.get(i)); } System.out.println("数据库连接失败!"); } return isPassed; } /** * 执行数据库查询操作 * @param sql 要执行的SQL语句 * @return ResultSet 返回查询的结果集对象 */ public ResultSet execQuery(String sql) { rs = null; // 判断连接数据库是否成功 if (openConn()) { try { ps = conn.prepareStatement(sql); rs = ps.executeQuery(); } catch (SQLException e) { closeAll(); System.out.println("SQL:"+sql); e.printStackTrace(); } } else { closeAll(); System.out.println("SQL:"+sql); System.out.println("数据库连接失败!"); } return rs; } /** * 关闭所有数据库连接对象 */ public void closeAll() { if (conn != null) { try { conn.close(); conn = null; } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); ps = null; } catch (SQLException e) { e.printStackTrace(); } } if (rs != null) { try { rs.close(); rs = null; } catch (SQLException e) { e.printStackTrace(); } } } }
评论
1 楼
327764984
2017-01-20
CommonSql里
不知道把PreparedStatment和ResultSet作为实例属性保存的意义何在 它们既没有被复用 也没有被管理销毁 却在一次查询后一度持有引用阻止被GC
从生命周期角度 ResultSet短于PreparedStatment短于Connection 全部关闭操作也不是按这个顺序
不知道把PreparedStatment和ResultSet作为实例属性保存的意义何在 它们既没有被复用 也没有被管理销毁 却在一次查询后一度持有引用阻止被GC
从生命周期角度 ResultSet短于PreparedStatment短于Connection 全部关闭操作也不是按这个顺序
发表评论
-
向数据库插入中文乱码【转】
2015-05-02 19:35 1391又遇到乱码问题,这个编码问题有时候真是让人头大。找了半 ... -
tomcat web.xml配置(转)
2013-03-27 15:17 1196web.xml元素介绍 我将自 ... -
java获取URL内容截取后保存到Excel中
2012-11-01 16:27 2467通过java.net 访问相应url,过滤返回的信息,并保存 ... -
java 反射
2012-10-24 14:47 1118java反射是java控制反转 ... -
POI包说明
2012-10-18 13:40 1725在线Javadoc:http://www.osctool ... -
JAVA_IO详解_包括讲解IO中各种流及其用法
2012-10-18 13:21 1023个人感觉比较详细的javaIO资料,下载附件 -
Spring入门示例及相关概念介绍(转)
2012-07-01 15:38 1190Spring入门示例及相关概念介绍 作者:http:/ ... -
servlet中init()和service()方法的区别(转)
2012-06-26 14:43 1794servlet中init()和service() ... -
getRequestDispatcher()与sendRedirect()的区别(转)
2012-06-26 14:37 10771.request.getRequestDispatch ... -
JAVA数据结构(~转~)
2012-06-26 13:45 1138JAVA数据结构 线性表,链表,哈希表是常用的数据结构 ... -
Java多线程编程总结(转)
2012-06-18 09:59 1028Java多线程编程总结 下面是Java线程系 ... -
JAVA IO 设计模式彻底分析(转)
2012-06-15 20:01 1246我想任何一本介绍模式的书在讲到Decorator模式的时候不能 ... -
J2EE开发常用开源框架技术(转)
2012-06-14 16:36 8061主要就我所了解的J2EE开发的框架或开源项目做个介绍,可以根据 ... -
Oracle回滚注意事项
2012-04-11 17:27 1114回滚到fisrt()时注意使用next()时需要将光标移到第一 ... -
Date 和 Calender 的转化 (转)
2012-04-09 14:23 1519Date 和 Calender 的转化 ... -
创建Java线程池(转)
2012-03-30 17:30 1365线程池的作用: 线程池作用就是限制系统中执行线 ... -
对Servlet的初始化的理解
2012-03-12 11:33 1699在读我自己的认识之前 , 我们 ... -
用java调用oracle存储过程总结
2012-02-17 14:30 01、什么是存储过程。存储过程是数据库服务器端的一段程序,它 ... -
JAVA设计模式之工厂模式
2012-02-17 11:03 13054JAVA设计模式之工厂模 ... -
Java技术----实现JAVA的动态类载入机制
2012-02-17 10:44 1658----作为充分利用Java的 ...
相关推荐
Connection conn = ConnectionManager.getInstance().getConnection();这样来获得conn实体对象,然后就可以应用了。 conn.setAutoCommit(false);用事务提交 最后conn.commit(); conn.close();就可以了。
Connection con=ConnectionFactory.getConnection(); try{ con.setAutoCommit(false); st=con.createStatement(); String sql="insert into dept(name) values('gaoyajun')"; int i=st....
connection.setAutoCommit(false/true); 2. 提交事务 connection.commit(); 3. 回滚 connection.rollback(); - 实现转账: 超人 500 蝙蝠侠 5000 蝙蝠侠给超人转2000 执行第一次成功 执行第二次成功 执行第三...
1、JavaBean中使用JDBC事务处理 在JDBC中怎样将多个SQL语句组合成一个事务呢?在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到...
用JDBC时的一些注意事项 1.多使用PreparedStatement代替Statement这样可以避免在拼接字符串的时候出现 "select * from emp where name = '"+name+"'"单引号过多的情况 2 sql语句过长的时候尽量避免使用sql="str1"+...
public class JDBConnection { private final String ... con.setAutoCommit(true); } catch (SQLException e) { System.out.println(e.getMessage()); System.out.println("creatConnectionError!"); }
}}DBUtils事务操作Connection对象的方法名描述conn.setAutoCommit(false)开启事务new QueryRunner()创建核
2.建立连接 使用connection对象的getConnection方法 url(jdbc:oracle:thin:@ip:端口:数据库sid), user,password,如果要手动提交,调用conn.setAutoCommit(false) 3.创建statement对象 一个statement对象只能...
Oracle addBatch()用法实例详解 PreparedStatement.addbatch()的使用 Statement和...connection.setAutoCommit(false); 3.预编译SQL语句,只编译一回哦,效率高啊 PreparedStatement statement = co
RadSqlCmd radSqlCmd = RadSqlCmd.setAutoCommit(false); argsList = new ArrayList(); argsList.add("%2%"); System.out.println( radSqlCmd.sqlList("select * from ztest where tname like ?", args...
public static void StartTransaction(Connection con, String[] sqls) throws Exception { if (sqls == null) { return; } Statement sm = null; try { // 事务开始 System.out.println("事务处理...
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Iterator...
//con.setAutoCommit(false);//添加事物,既是否自动提交 stmt=con.createStatement(); } catch (SQLException e) { e.printStackTrace(); } } public Statement getStmt(){ return stmt; } public ...
private Connection conn = null; { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.out.println("创建驱动失败"); e.printStackTrace(); } try {...
为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示: conn.setAutoCommit(false); 值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用...
代码如下:con.setAutoCommit(true);//设为true,每次executeUpdate将立刻被执行 sql = “insert into table1(lable1) values(‘001’)”; rs = stmt.executeUpdate(sql); sql = “insert into table2(lable2) values...
Connection.setAutoCommit(false); 正常: conn.commit(); 异常: conn.rollback(); JDBC批处理: addBatch executeBatch Statement PreparedStatement Statement{ 1.获取连接 getConnection(); 2.创建...
dbUtil.getCon().setAutoCommit(false); //将订单中的数据录入数据库 pstmt_order = dbUtil.getCon().prepareStatement(sql_order); pstmt_order.setString(1, order.getUser().getName()); pstmt_...
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Savepoint; import java.sql....