一、PreparedStatement 预编译SQL执行器
由于在登陆功能中,出现任意字符都可以登录,导致该功能有“bug” ,其原因是Statement在执行的sql语句中,其参数注入sql关键字的问题,导致sql失效
可以使用Statement的子接口PreparedStatement解决sql注入异常
使用参数占位
public static boolean userLogin(String username,String password){
// 使用jdbc
// 导入jar包
// 加载驱动类
Connection conn=null;
PreparedStatement pst=null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/j2008_db?useSSL=false&serverTimezone=GMT%2B8";
//获取连接对象
conn = DriverManager.getConnection(url,"root","123456");
//执行SQL语句 对于参数使用?占位
String sql ="select * from my_user where user_name=? and user_password=?";
// 获取预编译的sql执行器
pst = conn.prepareStatement(sql);
//设置参数 : 有多少个?需要设置多少个参数 参数类型和问号的字段类型一致
pst.setString(1 , username );
pst.setString(2, password);
//执行sql语句
rs= pst.executeQuery();
if(rs.next()){
return true;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally{
try{
if(rs!=null){
rs.close();
}
if(pst!=null){
pst.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
用户注册:
// 使用Prepared完成用户注册功能
public static boolean register (String username,String password ,int age, String sex ){
// 使用jdbc
// 导入jar包
// 加载驱动类
Connection conn=null;
PreparedStatement pst=null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/j2008_db?useSSL=false&serverTimezone=GMT%2B8";
//获取连接对象
conn = DriverManager.getConnection(url, "root", "123456");
String sql="insert into my_user values(null,?,?,?,?,now())";
// 获取预编译sql执行器
pst = conn.prepareStatement(sql);
//设置参数
pst.setString(1,username);
pst.setString(2,password);
pst.setInt(3,age);
pst.setString(4,sex);
int count = pst.executeUpdate(); //不能有sql参数 否则会覆盖之前的sql模板
if(count>0){
return true;
}
}catch(Exception ee){
ee.printStackTrace();
}finally{
try{
if(rs!=null){
rs.close();
}
if(pst!=null){
pst.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
对于在添加数据时,主键通常是自增长,如果想要在添加数据成功后,反向获取该主键 ,需要在添加sql是设置一个标识 Statement.RETURN_GENERATED_KEYS
并通过 getGenerateKeys() 获取主键id
Statement.RETURN_GENERATED_KEYS
rs = pst.getGeneratedKeys();
// 获取预编译sql执行器
pst = conn.prepareStatement(sql ,Statement.RETURN_GENERATED_KEYS);
//设置参数
pst.setString(1,"张三");
pst.setString(2,"123");
pst.setInt(3,22);
pst.setString(4,"男");
// 通过系统时间 设置 Date
String str="2020-09-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date dd = sdf.parse(str);
pst.setDate(5,new Date(dd.getTime()));
// 执行
int count = pst.executeUpdate();
if(count>0){
//获取主键id
rs = pst.getGeneratedKeys();
//将结果集往后移动一位
rs.next();
System.out.println("添加成功,其id:"+rs.getInt(1));
}
// 应用场景: 需要添加订单表(主表)和订单明细表(子表)
// 先添加订单主表 ,此时会生成订单主键 id
// 再添加多条订单明细: 添加明细是 其它所属的 订单id也需要同时添加, 这是 可以通过getGeneraterKeys 和获取
// orderId
二、封装DBUtil
package com.j2008.jdbc2;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* ClassName: DBUtil
*/
public class DBUtil {
static String driverClass;
static String url;
static String username;
static String password;
static {
try {
// 加载驱动
Class.forName(driverClass);
// 读取db.propertes 文件
// 1、根据当前类的类加载器获取文件地址的输入流
InputStream is = DBUtil.class.getClassLoader().
getResourceAsStream("db.properties");
// 读取类路径的相对地址
Properties pro = new Properties();
// 通过属性工具类将一个属性文件的输入流加载(序列化的过程)
pro.load(is);
// getProperty(key)
driverClass = pro.getProperty("driverClass");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据连接
*/
public static Connection getConn() {
Connection conn = null;
try {
// 获取连接
conn = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭所有连接
* @param conn
* @param st
* @param rs
*/
public void closeAll(Connection conn , Statement st , ResultSet rs){
try{
if(rs!=null){
rs.close();
}
if(st!=null){
st.close();
}
if(conn!=null){
conn.close();
}
}catch (Exception ee ){
ee.printStackTrace();
}
}
public static void main(String[] args) {
}
}