1.使用PreparedStatement
1)使用Statement 需要进行拼写SQL语句 ,很辛苦 而且容易出错
PreparedStatement 是Statement的子接口,可以传入带占位符的sql语句
并且提供了补充占位符变量的方法
2)使用PreparedStatement步骤
a.创建PreparedStatement:
String sql = “”insert into student valuse(?,?,?,?)”;
PreparedStatement ps = conn.preparedStatement(sql );
b.调用PreparedStatement的setXXX(int index, Object obj);设置占位符的值
注意:索引值index从1开始
c.执行sql语句:executeQuery()或 executeUpdate().注意执行时不再需要传入sql语句
示例代码如下:
JDBCTools.java
package com.atchance.jdbc;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* JDBCTools类中定义了:
* 1,数据库连接方法
* 2.数据库进行增删改的方法
* 3.数据库相关连接的释放
* 1)重载了release函数 :传两个参数 以及传三个函数
* @author chance
*
*/
public class JDBCTools {
public static void release(ResultSet rs,Statement statement, Connection con) throws SQLException{
/**
* 释放ResultSet Statement Connection三个连接的方法
*/
try {
if(rs != null)
rs.close();
} catch (Exception e1) {
e1.printStackTrace();
}
try {
if(statement != null)
statement.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(con != null)
con.close();
}
}
public static void release(Statement statement, Connection con) throws SQLException{
/**
* Statement Connection两个连接的方法
*/
try {
if(statement != null)
statement.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(con != null)
con.close();
}
}
public static Connection getConnection() throws Exception{
/*
* 创建数据库的连接
* */
String driverClass = "oracle.jdbc.driver.OracleDriver";
String jdbcUrl = "jdbc:oracle:thin:@localhost:1521:ORCL";
String user = "scott";
String password = "tiger";
Driver driver = (Driver)Class.forName(driverClass).newInstance();
Properties info = new Properties();
info.put("user", user);
info.put("password", password);
Connection connection = driver.connect(jdbcUrl,info);
return connection;
}
public void update_1() throws Exception{
/**
* 这个update函数使用的是PreparedStatement对象进行更新 不需要进行sql语句的拼接
*/
Connection con = null;
PreparedStatement ps = null;
try {
//获取连接
con = JDBCTools.getConnection();
//准备sql语句
String sql = "insert into student values(?,?,?,?)";
ps = con.prepareStatement(sql);
//调用PreparedStatement的setXXX(int index, Object obj);
ps.setString(1, "90010");
ps.setString(2, "张三");
ps.setString(3, "男");
ps.setString(4, "北京");
//执行sql语句
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭相应数据源
JDBCTools.release(null, ps, con);
}
}
}
2.使用PreparedStatement的好处
1).代码的可读性和可维护性
2)PreparedStatement尽最大可能提高性能.
3)最重要的一点是极大地提高了安全性
即sql注入,关于这点详见另一篇博客利用万能密码登陆网站后台原理及漏洞修复方法
PreparedStatment可以防止SQL注入。
如:String sql = “SELECT * FROM user WHERE name = ‘” + userName + “’ and password = ‘”+ passWord +”’;”
恶意输入参数值:userName = “1’ OR ‘1’=’1”; passWord = “1’ OR ‘1’=’1”;
最终sql会变成:String sql = “SELECT * FROM user WHERE name = ‘1’ OR ‘1’=’1’ and password = ‘1’ OR ‘1’=’1’;”
这条语句相当于select * from user。
如果用户再加上drop table user,后果将不堪设想。
所以使用PreparedStatement能避免此种情况,因为数据库系统不会将参数的内容视为SQL指令的一部分来处理,只有在数据库完成SQL指令的编译后,才套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。
4)相同操作批量数据效率较高