光链接池缺陷-PreparedStatement关闭后,ResultSet竟然能够继续使用

2021年11月26日 阅读数:7
这篇文章主要向大家介绍光链接池缺陷-PreparedStatement关闭后,ResultSet竟然能够继续使用,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

相信不少接触过JDBC的人都知道,Connection,PreparedStatement,ResultSet三者之间存在依赖关系,关闭上级,那么下级会自动失效,可是这也只是常规认识,凡事也有例外,直接上代码java

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class TestPreparedStatementOnHikaCP {

    public static void main(String[] args) {
        try {
            HikariConfig config2 = new HikariConfig();
            config2.setJdbcUrl("jdbc:mysql://localhost/test?serverTimezone=UTC");
            config2.setDriverClassName("com.mysql.cj.jdbc.Driver");
            config2.setUsername("root");
            config2.setPassword("");
            config2.setAutoCommit(false);
            config2.addDataSourceProperty("cachePrepStmts", "true");
            config2.addDataSourceProperty("useServerPrepStmts", "true");
            HikariDataSource ds = new HikariDataSource(config2);

            ResultSet rs=null;
            Connection con = null;
            try {
                con = ds.getConnection();
                PreparedStatement pst=con.prepareStatement("select * from BEECP_TEST");
                rs=pst.executeQuery();
                pst.close();
                while(rs.next())
                    System.out.println(rs.getString(1));
                /**
                 * 依赖包:
                 * 1:HikariCP-3.4.5.jar
                 * 2:mysql-connector-java-8.0.16.jar
                 */
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (rs!= null)
                    rs.close();
                if (con != null)
                    con.close();
            }
            ds.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果截图mysql

结论:Mysql的JDBC驱动实现,在ServerCache模式下,ResultSet与PreparedStatement是关系脱节的,也就是说PreparedStatement关闭时,不会自动关闭由它打开过的RessultSet. 对于链接池而言,从安全角度出发,是须要主动尝试去关闭打开过的ResultSet, 所以也能够说光链接池在使用Mysql驱动的时候存在这个隐患,有可能做者是知道在ServerCache模式下存在这个问题,可是为了极度精简代码追求高性能而有意忽略为之。光链接池流行多年了,不知道有没有人发现这个问题。sql

提醒:使用JDBC的时候,必定不要忘记使用标准的关闭写法安全

try{

  .......

}finally{
  rs.close();
  pst.close();
  con.close();
}