1. 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();
    }
    }
    }
    }

setAutoCommmit保持数据的完整性的更多相关文章

  1. oracle维护数据的完整性

    介绍: 数据的完整性用于确保数据库数据遵从一定的商业的逻辑规则.在oracle中,数据完整性可以使用约束.触发器.应用程序(过程.函数)三种方法来实现,在这三种方法中,因为约束易于维护,并且具有最好的 ...

  2. MySQL——保证数据的完整性

    为了防止垃圾的产生,从而影响数据库的执行效率. 1实体完整性——行数据的有效性   唯一约束(unique).主键约束(primary key) 2域完整性——列数据的有效性 非空约束(not nul ...

  3. 代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性

    做人事档案的系统考虑到数据的安全性与一致性,毕竟是要对外上线.真正投入使用的项目,数据库的可靠性与安全性上我们开发人员要考虑的就很多了,记得做机房收费系统时注册新卡是自己为了简单,写成了一个存储过程( ...

  4. Oracle 维护数据的完整性 一 索引

    简介:索引是用于加速数据存取的数据对象,合理的使用索引可以大大降低i/o 次数,从而提高数据的访问性能. 当我们从一张表中检索我们需要的数据是,oralce往往会进行全表扫描,就是遍历所有的数据行,来 ...

  5. Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?

    1.kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的 ...

  6. Oracle 维护数据的完整性 一 约束

    简介:约束用于确保数据库满足特定的商业规则.在Oracle中,约束包括以下几种: 1.not null      非空约束       该劣质不能为null 2.unique       唯一约束   ...

  7. 从零自学Hadoop(16):Hive数据导入导出,集群数据迁移上

    阅读目录 序 导入文件到Hive 将其他表的查询结果导入表 动态分区插入 将SQL语句的值插入到表中 模拟数据文件下载 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并 ...

  8. 大数据系列(2)——Hadoop集群坏境CentOS安装

    前言 前面我们主要分析了搭建Hadoop集群所需要准备的内容和一些提前规划好的项,本篇我们主要来分析如何安装CentOS操作系统,以及一些基础的设置,闲言少叙,我们进入本篇的正题. 技术准备 VMwa ...

  9. MVVM中数据验证之 ViewModel vs. Model

                                                      MMVM模式示意图. View绑定到ViewModel,然后执行一些命令在向它请求一个动作.而反过来 ...

随机推荐

  1. Sql Server 2012 Enterprise Edition 企业版 迅雷 下载地址

    Sql Server 2012 Enterprise Edition 企业版 迅雷 下载地址 版本号 cn_sql_server_2012_enterprise_edition_x86_x64_dvd ...

  2. highchart访问一次后台服务返回多张图表数据

    本文承接上一篇,我们制作动态图表的时候,往往需要的不止一张图表,如果每张图表都与服务接口做一次交互的话未免太过频繁,这无论对前后还是后台都是一种压力,本文介绍一种一次访问返回多组数据的方式来减少前台与 ...

  3. Git的基础

    http://backlogtool.com/git-guide/cn/intro/intro2_3.html

  4. s5pv210中断体系

    一.什么是中断? 1.中断的发明是用来解决宏观上的并行需要的.宏观就是从整体上来看,并行就是多件事情都完成了. 2.微观上的并行,就是指的真正的并行,就是精确到每一秒甚至每一刻,多个事情都是在同时进行 ...

  5. windows 下 gvim打开默认全屏显示

    在_vimrc文件中加入如下配置即可: autocmd GUIEnter * simalt ~x

  6. SQLServer2008R2 error 40解决方法

    实际遇到的问题,以下为搜到的解决方案,亲测可用 转自 http://blog.csdn.net/laga516/article/details/7696577 最近一直在配置服务器, 这当中最头疼的就 ...

  7. 利用C++不使用递归,循环和goto,打印1到100 的某一答案分析

    实验环境是在64位linux下使用g++编译器    下面是Mark Gordon的答案   The below one works on my system, can't guarantee res ...

  8. 解决:eclipse 非正常关闭,导致无法正常启动

    eclipse 无法正常启动: !ENTRY org.eclipse.ui.navigator 4 2 2016-09-07 11:23:54.181 !MESSAGE 从插件调用代码时出现问题:“o ...

  9. TCP数据包的封包和拆包

    //该段博文为引用,非原创. 封包和拆包 作者:fengge8ylf  博客:http://blog.csdn.net/fengge8ylf 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就 ...

  10. [转载]Matlab生成Word报告

    最近在进行一批来料的检验测试,一个个手动填写报告存图片太慢了,就有了种想要使用Matlab在分析完后数据可以自动生成PDF报告的想法,于是就去网上搜索了相关的资料,发现Matlab中文论坛上有xiez ...