码迷,mamicode.com
首页 > 其他好文 > 详细

Connection、Statement、PreparedStatement 、Resultset注意点备忘

时间:2015-12-08 16:19:09      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:jdbc

先记录一下几个测试结果

测试环境

MySQL:mysql-connector-java-5.1.29.jar

Java:1.7.0_67


测试A

代码:

        PreparedStatement pstmt = conn
                .prepareStatement("select id from world.city limit 3");
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            System.out.println(rs.getString(1));
        }
        System.out.println();

        PreparedStatement pstmt2 = conn
                .prepareStatement("select countrycode from world.city limit 3");
        ResultSet rs2 = pstmt2.executeQuery();
        while (rs2.next()) {
            System.out.println(rs2.getString(1));
        }

        System.out.println(pstmt.isClosed());
        System.out.println(rs.isClosed());
        System.out.println(pstmt2.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();

        conn.close();
        System.out.println(pstmt.isClosed());
        System.out.println(rs.isClosed());
        System.out.println(pstmt2.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();

结果:

false
false
false
false
false

true
true
true
true
true

结论:

connection关闭时会关闭关联的ResultSet和PreparedStatement。


测试B

代码:

        PreparedStatement pstmt = null;
        ResultSet rs1 = null;
        ResultSet rs2 = null;
        
        Statement st = null;
        ResultSet rs3 = null;
        ResultSet rs4 = null;
        
        try {
            pstmt = conn.prepareStatement(
                    "select name from world.city where name like ? limit 3");
            pstmt.setString(1, "a%");
            rs1 = pstmt.executeQuery();
            rs2 = null;
            while (rs1.next()) {
                System.out.println(rs1.getString(1));

                pstmt.setString(1, "b%");
                rs2 = pstmt.executeQuery();
                while (rs2.next()) {
                    System.out.println(rs2.getString(1));
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        try {
            st = conn.createStatement();
            rs3 = st.executeQuery(
                    "select name from world.city where name like ‘a%‘ limit 3");
            rs4 = null;
            while (rs3.next()) {
                System.out.println(rs3.getString(1));

                rs4 = st.executeQuery(
                        "select name from world.city where name like ‘b%‘ limit 3");
                while (rs4.next()) {
                    System.out.println(rs4.getString(1));
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(pstmt.isClosed());
        System.out.println(rs1.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(st.isClosed());
        System.out.println(rs3.isClosed());
        System.out.println(rs4.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();

结果:

java.sql.SQLException: Operation not allowed after ResultSet closed

java.sql.SQLException: Operation not allowed after ResultSet closed
    
false
true
false
false
true
false
false

结论:

同一个Statement或PreparedStatement对象只能关联一个激活的ResultSet。


测试C

代码:

        PreparedStatement pstmt = conn
                .prepareStatement("select id from world.city limit 3");
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            System.out.println(rs.getString(1));
        }
        System.out.println();
        
        PreparedStatement pstmt_old = pstmt;
        pstmt = conn.prepareStatement("select name from world.city where name like ? limit 3");
        pstmt.setString(1, "a%");
        ResultSet rs2 = pstmt.executeQuery();
        while (rs2.next()) {
            System.out.println(rs2.getString(1));
        }

        System.out.println(pstmt.isClosed());
        System.out.println(rs.isClosed());
        System.out.println(pstmt_old.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();
        
        pstmt.close();
        System.out.println(pstmt.isClosed());
        System.out.println(rs.isClosed());
        System.out.println(pstmt_old.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();

        conn.close();
        System.out.println(pstmt.isClosed());
        System.out.println(rs.isClosed());
        System.out.println(pstmt_old.isClosed());
        System.out.println(rs2.isClosed());
        System.out.println(conn.isClosed());
        System.out.println();

结果:

false
false
false
false
false

true
false
false
true
false

true
true
true
true
true

结论:

如果PreparedStatement对象没有关闭就关联了其他PreparedStatement,则旧的PreparedStatement和ResultSet不会关闭,直到Connection关闭。在使用连接池的情况下,可能造成内存泄露。


比较好的做法:

  1. 使用PreparedStatement代替Statement,一方面,多次提高了多次执行语句的效率,另一方面,防止拼接SQL可能造成的注入攻击

  2. 一定要注意关闭PreparedStatement,在使用连接池的情况下尤其要注意。Java7以上建议使用try-with-resource语句,简洁。Java7以下注意关闭时也要try-catch,并尽量按照ResultSet、PreparedStatement、Connection的顺序关闭。

  3. 不要传递ResultSet,使用RowSet。

本文出自 “不积跬步,无以至千里” 博客,请务必保留此出处http://wangzhichao.blog.51cto.com/2643325/1720656

Connection、Statement、PreparedStatement 、Resultset注意点备忘

标签:jdbc

原文地址:http://wangzhichao.blog.51cto.com/2643325/1720656

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!