JDBC之PreparedStatement接口

来源:互联网 发布:知之深爱之切电子书 编辑:程序博客网 时间:2024/05/20 23:29

PreparedStatement接口继承自Statement接口,用于执行含有或不含有参数的预编译的SQL语句,相对于Statement接口,用于执行静态SQL语句,PreparedStatement接口中的SQL语句是预编译的,重复执行的效率会比较高。
创建执行SQL的语句(Statement)

Statement与PreparedStatement区别

方式一:Statement
String sql = “select * from table_name where col_name=‘col_value’”;
Statement st = conn.createStatement();
st.executeQuery(sql);

方式二:PreparedStatement
String sql = “select * from table_name where col_name=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, “col_value”);
ps.executeQuery();

PreparedStatement对象用Connection接口中的preparedStatement方式创建,如为SQL语句insert创建一个PreparedStatement对象。5个问号用作参数的占位符分别代表Contacts中一条记录的Name,PhoneNumber,Email,QQ,Note的值。

PreparedStatement ps = conn.prepareStatement("insert into Contacts(Name,PhoneNumber,Email,QQ,Note) values(?,?,?,?,?)");

为SQL语句select语句创建一个PreparedStatemen对象。这条语句中的问号则代表Contacts中的Name的值。

PreparedStatement ps = conn.prepareStatement("select * from Contacts where Name=?");

作为Statement的子接口,在继承所有方法的同时,也提供了PreparedStatement对象中设置参数的方法,
setX(int Index,X value);
X是参数类型,Index为语句的下标,下标从1开始,如ps.setString(1,”jack”);

在设置完参数后就可以调用方法executeQuery()或者executeUpdate()执行预备好的语句,使用哪个方法取决于PreparedStatemen对象的功能,查询还是更新。只是这两个方法不需要参数,这与Statement接口中的同名方法不同。因为在创建的时候就已经指定了SQL语句。

优点

1.PreparedStatement接口继承Statement,它的实例包含已编译的SQL语句,执行速度要快于Statement。
2.PreparedStatement继承了Statement的所有功能,三种方法executeUpdate、executeQuery、execute不再需要参数。
3.在JDBC应用中,一般都用PreparedStatement,而不是Statement。

案例
利用PreparedStatement接口实现增的操作:

public class PstatementTest {        private static DbUtil dbUtil = new DbUtil();      private static int addMember(CompMember mem) throws Exception{          Connection con = dbUtil.getCon();          String sql = "insert into comp values(null,?,?,?)";          PreparedStatement pstmt = con.prepareStatement(sql);          pstmt.setString(1, mem.getName());          pstmt.setInt(2, mem.getAge());          pstmt.setDouble(3, mem.getSalary());          int result = pstmt.executeUpdate();//中间不用传入sql          dbUtil.close(pstmt, con); //preparedStatement是子类,用父类关闭也行          return result;          }      public static void main(String[] args) throws Exception {          CompMember mem = new CompMember("刘翔", 24, 8000.00);          int result = addMember(mem);          if (result==1) {              System.out.println("添加成功");          } else {              System.out.println("添加失败");          }      }  }  

再利用PreparedStatement接口实现查询,并运用ResultSet结果集:

public class ResultsetTest {      private static DbUtil dbUtil = new DbUtil();      /**      * 遍历查询结果       */      @SuppressWarnings("unused")      private static void listMem1() throws Exception {          Connection con = dbUtil.getCon();// 获取连接          String sql = "select * from comp";          PreparedStatement pstmt = con.prepareStatement(sql);          ResultSet rs = pstmt.executeQuery();// 返回结果集          // next()将光标向后一行          while (rs.next()) {              int id = rs.getInt(1);// 获取第一列的值id              String name = rs.getString(2);//              int age = rs.getInt(3);              double salary = rs.getDouble(4);              System.out.println("编号:" + id + "姓名:" + name + "年龄:" + age + "工资:" + salary);          }      }      /**      * 遍历查询结果方法2      */      @SuppressWarnings("unused")      private static void listMem2() throws Exception {          Connection con = dbUtil.getCon();// 获取连接          String sql = "select * from comp";          PreparedStatement pstmt = con.prepareStatement(sql);          ResultSet rs = pstmt.executeQuery();// 返回结果集          // next()将光标向后一行          while (rs.next()) {              int id = rs.getInt("id");// 获取第一列的值id              String name = rs.getString("name");//              int age = rs.getInt("age");              double salary = rs.getDouble("salary");              System.out.println("编号:" + id + "姓名:" + name + "年龄:" + age + "工资:" + salary);          }      }      private static List<CompMember> listMem3() throws Exception{          List<CompMember> memList = new ArrayList<CompMember>();          Connection con = dbUtil.getCon();// 获取连接          String sql = "select * from comp";          PreparedStatement pstmt = con.prepareStatement(sql);          ResultSet rs = pstmt.executeQuery();// 返回结果集          // next()将光标向后一行          while (rs.next()) {              int id = rs.getInt("id");// 获取第一列的值id              String name = rs.getString("name");//              int age = rs.getInt("age");              double salary = rs.getDouble("salary");              CompMember mem = new CompMember(id, name, age, salary);              memList.add(mem);//添加到List中               }          return memList;      }      public static void main(String[] args) throws Exception {  //      listMem1();  //      listMem2();          List<CompMember> memList = listMem3();          for (CompMember mem : memList) { //遍历集合的每个元素              System.out.println(mem);          }      }  }

重点:
一个简单的分页查询,顺便说一下,分页查询也是跟java中的规则一样,含前不含后。

    String sql = "SELECT call_time_start,call_time_end,tellphone from call_message  WHERE caid =? ORDER BY call_time_start limit ?,?";        PreparedStatement pstmt=con.prepareStatement(sql);        pstmt.setString(1, caid);        pstmt.setInt(2, (pageNo-1)*pageSize);        pstmt.setInt(3, pageNo*pageSize);        ResultSet rs=pstmt.executeQuery();        while(rs.next()){           //一些操作        }

对于sql注入这种情况是必须避免的。PreparedStatement与Statement最大的差别就是,PreparedStatement是将sql语句编译之后存储起来,然后对传过去的字段进行拼接,这样就可以避免一些非法用户对sql语句进行操作,而Statement是将sql语句与用户传递的字段进行拼接之后存储起来,这样用户就可以通过一些非法的sql拼接来处理,譬如我可以在用户名和密码后拼接 (or 1=1)这样的sql,无论你密码正不正确都会通过验证的,这样就会出现sql注入的问题。

所以在平时使用的时候选择使用PreparedStatement。
网上有很多使用sql直接传值拼接的,不建议使用这种方式。
一般我们选择这种方式,以set方式来设置这些参数值

        pstmt.setString(1, caid);        pstmt.setInt(2, (pageNo-1)*pageSize);        pstmt.setInt(3, pageNo*pageSize);

参考博客:
http://blog.csdn.net/Zhonger_MaTT/article/details/64993895

原创粉丝点击