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. 深入浅出讲解:php的socket通信

    对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问:1.         什么是TCP/IP.UDP?2.         Socke ...

  2. 《Pro Git》阅读随想

    之前做版本管理,我使用最多的是SVN,而且也只是在用一些最常用的操作.最近公司里很多项目都开始上Git,借这个机会,我计划好好学习一下Git的操作和原理,以及蕴含在其中的设计思想.同事推荐了一本< ...

  3. mongodb morphia关联查询一例

    //...此处省略了import... /** * Created by shenzhigang on 4/15/16. */ public class Main { public static vo ...

  4. 自定义Java集合

    一.泛型 1.在JDK1.4以前,所有的集合元素全都按照Object来存储,拿出来还要进行强制转型.由于这样的做法有太多的缺点,容易出现ClassCaseException,不安全,让人不省心,于是乎 ...

  5. 史航416第十次作业&总结

    作业1: 计算两数的和与差.要求自定义一个函数 #include <stdio.h> void sum_diff(float op1,float op2,float *psum , flo ...

  6. sql group by datetime on day

    SELECT        DATEADD(dd, DATEDIFF(dd, 0, postDate), 0)FROM          tableWHERE        (postDate > ...

  7. vs2010边调试边编辑后台.cs文件的办法

    方法一:在web项目的属性页里的web标签页,选中“启用编辑并继续”项 方法二:菜单 工具+选项+调试+编辑并继续,选中“启用编辑并继续”项. 设置完之后,调试web项目的时候可以直接修改.cs文件, ...

  8. C语言解析Ini格式文件

    引用别人的博文: http://www.open-open.com/lib/view/open1402278076447.html 可以解析 INI 格式的字符串.解析文件.保存到文件. 下面是头文件 ...

  9. Splinter学习--初探3,两种方式登录QQ邮箱

    目前,qq邮箱的登录方式有: 1.利用账号.密码登录 2.快捷登录,前提是你本地已有qq账号登录中 和前面一样,还是先到qq邮箱登录首页,审查页面元素,找到我们进行登录操作所相关的链接.按钮或是输入框 ...

  10. python集合(set)操作

    python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和 ...