* 1.由于含有动态信息,那么就需要先拼接SQL,这就可能出现SQL注入攻击的问题。
* 2.大部分情况下,拼接SQL时,语义已经定好,拼接的内容无非就是一些数据,
* 那么当大量执行这样含有动态值的SQL语句时,数据库每当接收到Statement发送的SQL语句时,
* 只要语句中的内容有区别,就会当做一条全新的SQL语句去执行,
* 数据库执行SQL时会首先解析SQL语句并生成一个 执行计划 (开销大),那么批量执行这样的内容有些微变化的
* SQL时,会为每一个SQL生成一个执行计划,对数据库是负担。
执行计划:一段可执行的代码
* java.sql.PreparedStatement
* 该接口是Statement的子接口,设计目的是为了执行动态SQL语句。
* 这样的SQL称为预编译SQL,这种SQL语句会将动态信息以“?”代替,
* 先进行占位,然后将该SQL发送给数据库生成的执行计划。
* 然后当需要执行该SQL时,只需要将?需要的时机数据再次传递给数据库即可。
*
* 1.由于先将SQL语句发送给数据库,并生成了执行计划(语义已经确定),
* 就不存在拼接SQL导致改变语义(SQL注入攻击)的问题了。
* 2.由于执行计划已经生成,当大批量执行SQL时,每次只需要将?表示的实际值传入,
* 那么数据库会重用执行计划,这就减少了服务器的压力。
//使用PreparedStatement
/*
* 预编译SQL语句,将动态部分以?代替
* 需要注意,?只能代替值,不能代替会改变SQL语句语义的部分
*/
EG:执行DQL
String sql = "SELECT id,username,password,email,nickname "
+ "FROM userinfo_snow "
+ "WHERE username=? AND password=? ";
/*
* 创建PreparedStatement时就需要将预编译SQL语句传入,
* 实际上在创建PS时就会将该SQL发送给数据库以生成执行计划。
*/
PreparedStatement ps = conn.prepareStatement(sql);
/*
* 在执行SQL的工作前,还需要将?部分的时机数据传递给数据库
*/
ps.setString(1, "MARRY");
ps.setString(2, "123");
ResultSet rs = ps.executeQuery();
if(rs.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
EG:执行DML
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@176.225.131.254:1521:orcl", "tarena", "tarena");
//使用PreparedStatement
String sql = " INSERT INTO userinfo_snow "
+ " (id,username,password,email,nickname,account) "
+ " VALUES "
+ " (seq_userinfo_snow_id.NEXTVAL,?,?,?,?,?) ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "Halin");
ps.setString(2, "123456");
ps.setString(3, "HL@qq.com");
ps.setString(4, "HL");
ps.setDouble(5, 6000);
int d = ps.executeUpdate();
if(d>0){
System.out.println("插入成功!");
}
EG:
/**
* 要求用户传入一个id,然后删除对应的用户
* 使用PreparedStatement完成
* @author Tarena-java
*
*/
public class JDBCDemo03 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个id:");
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@176.225.131.254:1521:orcl", "tarena", "tarena");
int id = scan.nextInt();
String sql = "DELETE userinfo_snow "
+ " WHERE id = ? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
int i = ps.executeUpdate();
if(i>0){
System.out.println("删除"+id+"对应的信息成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
EG:
/*
* 获取结果集元数据
*/
ResultSetMetaData rsmd = rs.getMetaData();
/*
* 查看结果集字段数量
*/
int count = rsmd.getColumnCount();
for(int i=1;i<=count;i++){
/*
* 查看指定字段的字段名
*/
String colName = rsmd.getColumnName(i);
System.out.println(colName);
}
建立一个管理数据库连接的类
1.定义静态属性
private static String className;
private static String url;
private static String userName;
private static String passWord;