zoukankan      html  css  js  c++  java
  • [J2EE] 有关 PreparedStatement

      今天同事遇到一个问题,简言之,就是PreparedStatement的预编译究竟是怎么发挥作用的...

      嘿嘿,说来惭愧,我以前就只知道PreparedStatement比Statement要好,要防SQL注入,就要用PS。

      But,它的预编译作用,我却没关注过。现在经过一番研究,我不敢说我已经“了解”了,但是总归是思路清晰了一些,

    我把我理解的整理出来希望对大家也有所帮助,有不对的地方请大家指正。

    •   预编译

      首先要说的就是“预编译”。我们知道数据库在执行SQL语句的时候,首先要解析这个SQL语句,有一个“执行计划”的概念(差不多就是指寻找执行这个sql语句的一个最优路径)。对于经常执行的sql,数据库会把执行计划给缓存起来,对应的key就是该条sql。那么当再次执行同样的sql的时候,数据库就不再解析了,直接根据key返回相应的执行计划。这就节省了很多时间。

    • PreparedStatement(后面简称PS)

      当我们说到PS的时候,可能我们会关心几个问题:

    1. 预编译发生在什么时候
    2. PS何时被缓存起来的

      回答第一个问题:

         “在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译”。

      回答第二个问题:

         是当我们执行PS的close()方法时~~~~

    •  TEST

    我针对PS cache,做了一个测验,想法是针对同一个SQL,如果我每次取到的PS都是同一个,说明确实是拿的缓存的....

    代码如下:

     1 import java.sql.Connection;
     2 import java.sql.DriverManager;
     3 import java.sql.PreparedStatement;
     4 import java.sql.SQLException;
     5 
     6 import oracle.jdbc.OracleConnection;
     7 
     8 
     9 public class Test
    10 {
    11      static Connection con = null;
    12     public static void main(String args[]) throws ClassNotFoundException, SQLException 
    13     {
    14         con = ((oracle.jdbc.OracleConnection)getConnection());
    15         PreparedStatement ps0 = getPS(con);
    16         ps0.close();
    17         PreparedStatement ps1 = getPS(con);
    18         ps1.close();
    19         System.out.println(ps0==ps1);//如果是true,说明cache发生了作用
    20         
    21         
    22         con.close();
    23         con = null;
    24         con = ((oracle.jdbc.OracleConnection)getConnection());
    25         PreparedStatement ps2 = getPS(con);
    26         ps2.close();
    27         con.close();
    28         System.out.println(ps1==ps2);//如果是false,说明connection关闭后,会重新缓存
    29     
    30     }
    31     
    32     //获取PS实例
    33     public static PreparedStatement getPS(Connection con)throws ClassNotFoundException, SQLException{
    34           
    35            String sql = "select * from cms_turbine t where t.mapping like ?";
    36            PreparedStatement ps1 = con.prepareStatement(sql);
    37            ps1.setString(1, "hello");
    38           return ps1;
    39     }
    40     
    41     //建立连接
    42     public static Connection getConnection(){
    43         if(con == null){
    44         try{
    45             Class.forName("oracle.jdbc.driver.OracleDriver");
    46             con = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1523:XXX",xx,xx);
    47 
    48 //下面两句是为了开启cache
    49             ((oracle.jdbc.OracleConnection)con).setImplicitCachingEnabled(true);
    50             ((oracle.jdbc.OracleConnection)con).setStatementCacheSize(10);
    51        }catch(Exception e){
    52            e.printStackTrace();
    53        }
    54         }
    55         return con;
    56     }
    57 }

    执行结果是: true

                      false

    说明同一个connection中两次取到的PS是同一个实例,不同connection不共用PS。

    Note:

    如果想要reuse PS,那再用完一个之后一定要close,意味着释放资源。在上面的代码中,如果main方法改写如下:

      public static void main(String args[]) throws ClassNotFoundException, SQLException 
        {
            con = ((oracle.jdbc.OracleConnection)getConnection());
            PreparedStatement ps0 = getPS(con);
            ps0.close();
            PreparedStatement ps1 = getPS(con);
    //        ps1.close();  ps1不close,后面ps2拿到的还是ps0吗?
            System.out.println(ps0==ps1);
            
            
            PreparedStatement ps2 = getPS(con);
            ps2.close();
            con.close();
            System.out.println(ps0==ps2);
        }

    执行结果是:true (因为ps0 close了)

                     false(因为ps1没有close,所以ps2并没有能拿到缓存中的PS)

    参考:

    http://www.linuxidc.com/Linux/2011-07/38776.htm

    http://docs.oracle.com/cd/E11882_01/java.112/e10589/stmtcach.htm#JJDBC28649

  • 相关阅读:
    【题解】【BT】【Leetcode】Populating Next Right Pointers in Each Node
    【题解】【BT】【Leetcode】Binary Tree Level Order Traversal
    【题解】【BST】【Leetcode】Unique Binary Search Trees
    【题解】【矩阵】【回溯】【Leetcode】Rotate Image
    【题解】【排列组合】【素数】【Leetcode】Unique Paths
    【题解】【矩阵】【回溯】【Leetcode】Unique Paths II
    【题解】【BST】【Leetcode】Validate Binary Search Tree
    【题解】【BST】【Leetcode】Convert Sorted Array to Binary Search Tree
    第 10 章 判断用户是否登录
    第 8 章 动态管理资源结合自定义登录页面
  • 原文地址:https://www.cnblogs.com/simple-code/p/4608181.html
Copyright © 2011-2022 走看看