一、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) {

}

}

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐