• JDBC异常处理和资源释放问题


    之前我们在介绍JDBC加载注册驱动的时候说过有三种方式,是哪三种方式呢?我们再来看看

    Class.forName("com.mysql.jdbc.Driver");
    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
    

    以上三种方式都可以实现JDBC的驱动加载注册,这里我们推荐使用Class.forName(“com.mysql.jdbc.Driver”);另外DriverManager.registerDriver(new com.mysql.jdbc.Driver());其实可以直接写成new com.mysql.jdbc.Driver();这里我们了解就好,大可不必深究,除非有必要!

    今天我们来说说JDBC连接数据库的异常的正确处理,还记得之前我们是怎么处理的吗?没错,我们直接给抛出了,代码是这个样子滴!

    
    @Test
          public void ddlAndExceptionTest() throws Exception{
    
    
                String sql = "CREATE TABLE `t_student` (`id` bigint(10)  DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
    
                //加载注册驱动
                Class.forName("com.mysql.jdbc.Driver");
    
                //获取连接对象
                Connection connection =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root",  "123456");
    
                //创建获取语句对象
                Statement st = connection.createStatement();
    
                //执行SQL语句
                st.executeUpdate(sql);
    
                //释放资源
                st.close();
                connection.close();
    
          }
    

    我们这里直接throws Exception了,其实这样是不妥的,那正确的异常处理方式是什么呢?在此之前我们应该知道处理异常我们都用try catch的,有时候也配合finally一起使用,在处理JDBC连接数据库的异常时我们需要着重了解的还有资源释放的问题,就是那个xxx.close,下面我们一步步结合代码来说

    首先我们看需要处理异常的代码

    这里写图片描述

    诸如此类的代码异常我们都将它使用try catch包裹

    
     //加载注册驱动
                try {
                      Class.forName("com.mysql.jdbc.Driver");
                } catch (ClassNotFoundException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                }
    

    然后将catch中的异常类型改为Exception,然后继续写代码,完成JDBC连接数据库的后续步骤,代码如

     try {
                      //加载注册驱动
                      Class.forName("com.mysql.jdbc.Driver");
                      //获取连接对象
                      Connection connection =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                      //创建或者获取语句对象
                      Statement statement = connection.createStatement();
                      //执行sql语句
                      statement.executeUpdate(sql);
                      //释放资源
                      statement.close();
                      connection.close();
    
                } catch (Exception e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                }
    

    到这里我们就已经将异常做了相应的处理,但是这里面还有个很大的问题那就是资源释放的问题,也就是说目前释放资源的代码放在那里是不妥的,如果之前代码出现个什么意外,那么资源就无法释放了,可能有人说了,为什么这个资源必须要释放呢?

    那么我们就来说道说道这个资源为什么必须释放呢?
    我们先来看这个Connection,这家伙是数据库的连接对象,你可要知道在JDBC中Connection这个资源是非常稀有的,使用之后必须马上释放,我记得在哪看过关于这块释放资源的一个原则好像是“晚点用,早点放”,嗯,大概就是这个意思,总之在使用的过程中只有用到的时候才去创建这个对象,使用之后也要记得立马释放。

    因此,为了保证资源的必须释放,我们该怎么做呢?没错,我们可以将释放资源的代码放到finally里,这样就可以保证无论之前的代码怎样,释放资源的代码必定执行。

    这样代码就变成了现在这个样子了

    
     @Test
          public void testException(){
                String sql = "CREATE TABLE `t_one` (`id` bigint(10) DEFAULT  NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
                Statement statement = null;
                Connection connection = null;
                try {
                      //加载注册驱动
                      Class.forName("com.mysql.jdbc.Driver");
                      //获取连接对象
                      connection =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                      //创建或者获取语句对象
                      statement = connection.createStatement();
                      //执行sql语句
                      statement.executeUpdate(sql);
                      //释放资源
                      statement.close();
                      connection.close();
    
                } catch (Exception e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                } finally {
                      //释放资源
                      try {
                            statement.close();
                            connection.close();
                      } catch (SQLException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                      }
    
                }
    
    
          }
    

    到了这一步,你看看是不是就可以了呢?其实不然,这里面还是不行,哪里不行呢?我们来看,假如在connection没有来得及赋值的时候出现了意外,这样就会直接执行finally里面的代码,这样就会导致一个空对象调用close,就会引起新的异常导致程序崩溃,对于statement依然如此,因此,我们需要进行判空!

    因此finally里面释放资源的代码应该这样写

    
    finally {
                      //释放资源
                      if (statement!=null) {
                            try {
                                  statement.close();
                            } catch (SQLException e) {
    
                                  e.printStackTrace();
                            }finally {
                                  if (connection!=null) {
                                        try {
                                              connection.close();
                                        } catch (SQLException e) {
    
                                              e.printStackTrace();
                                        }
                                  }
                            }
                      }
    
                }
    

    因此正确完整的代码如下

    
     //正确处理JDBC的异常
          @Test
          public void testHandleException(){
    
                Connection con = null;
                Statement st = null;
                String sql = "CREATE TABLE `t_new1` (`id` bigint(10) DEFAULT  NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
    
                //异常标准代码格式结构
                try{
    
                      //这里存放可能出现异常的代码
                      //加载注册驱动
                      Class.forName("com.mysql.jdbc.Driver");
                      //获取连接对象
                      con =  DriverManager.getConnection("jdbc:mysql:///jdbcdemo","root","123456");
                      //获取连接语句
                      st = con.createStatement();
                      //执行sql语句
                      st.executeUpdate(sql);
    
                }
                catch (Exception e) {
    
                      e.printStackTrace();
                }finally {
                      //释放资源、
                      if (st!=null) {
                            try {
                                  st.close();
                            } catch (Exception e2) {
                                  // TODO: handle exception
                            }finally {
                                  if (con!=null) {
                                        try {
                                              con.close();
                                        } catch (Exception e3) {
                                              // TODO: handle exception
                                        }
                                  }
                            }
                      }
                }     
          }
    

    欢迎关注微信公众号:一个自学的程序员

  • 相关阅读:
    64位机配置iis 运行asp.net 程序(转载)
    病狗问题
    如何配置sqlcachedependence
    操作应用程序池
    自定义事件
    以下事情没做好决不能给客户演示
    判断用户ip是否在指定的ip段内
    silverlight4学习中解决的问题
    日历JS代码
    自己写的代码生成器ltscode2.0
  • 原文地址:https://www.cnblogs.com/ithuangqing/p/12113668.html
Copyright © 2020-2023  润新知