0、示例程序说明
- 演示登录验证,用户通过终端输入用户名与密码,程序连接数据库查询合法性;
- 基本步骤:
- 获取数据库连接对象
- 获取SQL执行对象
- 执行SQL获取结果对象
- 处理结果
- 执行SQL语句有两个类,Statement与PrepareStatement,后者是前者的子类,后者有防SQL流入的功能
1、封装工具类操作数据库
package com.yusian.utils;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class Utils {
private static String url; // 数据库连接url
private static String user; // 数据库用户名
private static String pass; // 数据库密码
private static String driver;
/**
* 读取配置文件初始化参数值
*/
static {
// 通过ClassLoader获取配置文件的路径
ClassLoader loader = Utils.class.getClassLoader();
URL jdbc = loader.getResource("jdbc.properties");
try {
// 通过Properties类读取配置文件中的数据,赋值给静态变量
Properties prop = new Properties();
prop.load(new FileReader(jdbc.getPath()));
url = prop.getProperty("url");
user = prop.getProperty("user");
pass = prop.getProperty("pass");
driver = prop.getProperty("driver");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return 数据库连接对象Connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
// 注册MySQL驱动类
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取MySQL连接对象
return DriverManager.getConnection(url, user, pass);
}
/**
* 释放更新类数据库操作对象
* @param conn 数据库连接对象
* @param stmt SQL语句执行对象
*/
public static void releaseExcuteUpdate(Connection conn, Statement stmt) {
releaseCloseableObject(stmt);
releaseCloseableObject(conn);
}
/**
* 释放查询类数据库操作对象
* @param conn 数据库连接对象
* @param stmt SQL执行对象
* @param retSet 查询结果
*/
public static void releaseExecuteQuery(Connection conn, Statement stmt, ResultSet retSet) {
releaseCloseableObject(retSet);
releaseExcuteUpdate(conn, stmt);
}
/**
* 释放资源
* @param object 需要释放的资源对象
*/
private static void releaseCloseableObject(AutoCloseable object) {
if (object == null) return;
try {
object.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、字符串拼接SQL语句的方式实现查询
/**
* 数据库验证用户名及密码的正确性
*
* @param username 用户名
* @param password 密码
* @return 验证结果
*/
private static boolean login(String username, String password) {
Connection conn = null;
Statement stmt = null;
ResultSet retSet = null;
// 拼接查询语句SQL
String sql = "select * from user where username = '" + username + "' and password = '" + password + "'";
try {
conn = Utils.getConnection();
stmt = conn.createStatement();
// 获取查询结果,有结果表明验证成功,无则失败
retSet = stmt.executeQuery(sql);
return retSet.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
Utils.releaseExecuteQuery(conn, stmt, retSet);
}
return false;
}
3、防SQL注入的实现方式
/**
* 数据库验证用户名密码的正确性,防SQL流入方法
* @param username 用户名
* @param password 密码
* @return 验证结果
*/
private static boolean login2(String username, String password) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet retSet = null;
try {
conn = Utils.getConnection();
// 这里是与Statement最本质的区别点,SQL中的变量用?占位,通过setXxxx方法赋值来规避SQL注入
pstmt = conn.prepareStatement("select * from user where username = ? and password = ?");
// 给SQL中占位符赋值,序号从1开始
pstmt.setString(1, username);
pstmt.setString(2, password);
retSet = pstmt.executeQuery();
return retSet.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
Utils.releaseExecuteQuery(conn, pstmt, retSet);
}
return false;
}