【实体类】
由于Java语言是面向对象编程的,而我们所使用的数据库面向关系的关系型数据库,因此在Java程序就会出现面向关系的数据库处理代码,从而违反Java语言面向对象的宗旨。为了解决这类问题,提出一个采用实体类来封装数据库中存储的数据记录以及它们之间的关系,从而解决Java语言与数据库操作的不统一性。
实体类与表对应(即User类对应表t_user),实体类中的属性与表中的字段对应
表中的一条记录,对应一个实体类的对象,该条记录每个字段的数据,赋值到实体对象的相应的属性上
创建一个实体对象用于封装表中的一条记录
- 五、掌握PreparedStatement接口的使用
PreparedStatement 接口继承 Statement接口
PreparedStatement比普通的Statement对象使用起来更加灵活,更有效率
当需要多次调用同一条SQL语句时,可以使用PreparedStatement
PreparedStatement从Statement继承而来。
setXXX方法
PreparedStatement解决了三个问题:
- 拼接字符串问题(所写SQL语句是不需要外来值侵入的,一个完整的字符串即可)
- 安全隐患问题(自动解决了SQL注入的问题,会自动将注入的有特别含义的字符串进行转义,例如:单引号,or关键字等)
- 效率问题(预编译,使字符串提前编译为数据库认识的语句)
所写SQL如果有外来值的侵入就使用PreparedStatement,如果没有外来值的侵入则使用Statement
package com.preparedstatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.domain.User;
import com.utils.JdbcUtils;
/**
* PreparedStatement示例
*/
public class PreparedStatement_Insert_Demo {
public static void main(String[] args) throws Exception{
PreparedStatement_Insert_Demo pid = new PreparedStatement_Insert_Demo();
pid.insertDateWithPreparedStatement("zhang3","z123");
}
public void insertDateWithPreparedStatement(String name, String password) throws SQLException{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "insert into T_PREPAREDSTATEMENT_CLOB_BLOB(id,name,password) values(myseq.nextval,?,?)";
conn = JdbcUtils.getConnectionForOracle();
/*
* 在创建PreparedStatement(预编译)语句时,在创建时就把相应的SQL语句提供给Connection,这时就会对SQL语句中的特殊字符进行处理(即过滤)
同时还会对PreparedStatement的性能进行优化处理,而Statement是无法完成这些工作的
*/
pstmt = conn.prepareStatement(sql);
//将?替换成具体的值
pstmt.setString(1, name);
pstmt.setString(2, password);
//由于在创建PreparedStatement时就已经提供了SQL语句,所以在执行时就不需要再提供SQL语句了
int i = pstmt.executeUpdate();
/**
* 注意:在使用PreparedStatement时,在执行executeUpdate()或executeQuery()方法时,一定要注意在这两个方法中是没有参数的,如果在
* 这两个方法中写上某个SQL语句,则此时执行的这两个方法则是Statement中的executeUpdate()或executeQuery()方法,因为这两方法是带参数的
* 而PreparedStatement自己的executeUpdate()或executeQuery()方法是不带参数的
*
* */
//int row = pstmt.executeUpdate(sql);
System.out.println("i= " + i);
JdbcUtils.free(rs, pstmt, conn);
}
}
【SQL注入-PreparedStatement和Statement 】
在SQL中包含特殊字符或SQL的关键字(如:‘ or 1 or ’或’or 1=1 or’)时Statement将出现不可预料的结果(出现异常或查询的结果不正确),可用PreparedStatement来解决。
PreperedStatement相对Statement有如下优点:
- 没有SQL注入的问题。
- Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。
- 数据库和驱动可以对PreperedStatement进行优化(只有在相关联的数据库连接没有关闭的情况下有效)。
【常见SQL注入字符串】
'or 1 or '
'or 1 or ''='
'or 1=1 or '
' or 1=1 or ''='
【数据类型转换(一)】
详细信息见java.sql.Types
日期类型转换
Date, Time, Timestamp --> date, time, datetime(java.sql包中的)
存:ps.setDate(i,d);
ps.setTime(i,t);
ps.setTimestamp(i, ts);
取:rs.getDate(i);
rs.getTime(i);
rs.getTimestamp(i);
package com.preparedstatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.domain.User;
import com.utils.JdbcUtils;
public class PreparedStatement_InsertAndSelect_DateType {
public static void main(String[] args) throws Exception{
PreparedStatement_InsertAndSelect_DateType piasd = new PreparedStatement_InsertAndSelect_DateType();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//向数据库中插入Date类型数据时,Statement与PreparedStatement的不同写法
//当使用Statement类时,如果要向数据库中存储Date类型的数据,需要在程序中将Date类型转换成String类型,然后再使用数据库的相关函数进行类型转换
piasd.insertDateWithStatement("wang5","w123",sdf.format(new Date()));
//使用PreparedStatement时,如果要向数据库中存储Date类型的数据,则不需要转换成String类型
// piasd.insertDateWithPreparedStatement("zhao6","z123",new Date());
//插入带时间部分的日期,即:日期 和时间
// piasd.insertDateWithPreparedStatement_Timestamp("timestamp", "p000", new Date());
//查询date类型字段的值,返回的类型为:java.util.Date,此时该Date对象只包括日期部分,而没有时间部分,查询条件为:根据主键值查询
// Date d1 = piasd.selectDateWithPreparedStatement(243);
// System.out.println("d1: " + d1);
//查询date类型字段的值,返回的类型为:java.util.Date,此时该Date对象包括日期部分和时间部分,查询条件为:根据主键值查询
/*
Date d2 = piasd.selectDateWithPreparedStatement_Timestamp(243);
System.out.println("d2: " + d2);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf2.format(d2));
*/
}
/**
* 功能:使用Statement完成Date类型字段值的插入
*/
public void insertDateWithStatement(String name, String password, String date) throws SQLException{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String sql = "insert into T_PREPAREDSTATEMENT_CLOB_BLOB(id,name,password,birthday) values(myseq.nextval,'" + name +"',&