1.提供JDBC工具类
//提供丰富的方法,方便的jdbc操作
public class JDBCUtils2 {
//1,获取数据库的连接(注册驱动+获取连接)
/**
* 获取数据库的连接
* @return 数据库的连接对象Connection
* @throws Exception
*/
static public Connection getConnection() throws Exception{
//1,注册驱动
Class.forName("com.mysql.jdbc.Driver");//全路径
//2,获取数据库的连接(用户名/密码)
//jdbc连接mysql数据库的协议//本机:端口号/数据库的名字 解决中文乱码 指定时区 关闭权限检验
String url="jdbc:mysql://localhost:3306/cgb2108?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false" ;
Connection c = DriverManager.getConnection(
url,"root","root");
return c ;//返回给调用者
}
/**
* @param resultSet 返回结果集
* @param preparedStatement 获取传输器
* @param connection 获取连接
*/
public static void close(
ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
2.模拟用户登录,解决SQL注入问题
package cn.tedu.jdbc;
import java.sql.*;
import java.util.Scanner;
//需求:利用JDBC,查询tb_user表里的数据
/* 1,创建表,并插入数据 2,利用JDBC,查询数据
CREATE TABLE tb_user(
id int PRIMARY KEY auto_increment,
name varchar(20) default NULL,
password varchar(20) default NULL
)
insert into tb_user values(null,'jack','321')
*/
public class Test2 {
public static void main(String[] args) throws Exception {
// method();//查询tb_user表里的数据
// method2();//模拟用户登录
method3();//解决SQL攻击问题
}
//解决SQL攻击问题
private static void method3() throws Exception {
//1,注册驱动 2,获取连接
Connection c = JDBCUtils.getConnection();
//3,执行SQL
String a = new Scanner(System.in).nextLine();//用户名
String b = new Scanner(System.in).nextLine();//密码
//如果动态的拼接字符串时,数据在中间的位置 "+a+"
// String sql="select * from tb_user where name='jack' and password='321'" ;
// String sql="select * from tb_user where name='"+a+"' and password='"+b+"'" ;
//SQL骨架:用?代替了参数的位置,?叫占位符,好处:简洁(避免了SQL拼接参数)
String sql="select * from tb_user where name=? and password=?" ;
//4,获取传输器
// Statement s = c.createStatement();
PreparedStatement s = c.prepareStatement(sql);
//设置SQL参数--setXxx()设置不同类型的参数
s.setString(1,a);//?的索引,要给?设置的值
s.setString(2,b);//?的索引,要给?设置的值
//TODO 当用户名输入jack'#时还会发生SQL攻击吗???
ResultSet r = s.executeQuery();
//5,解析结果集
if(r.next()){//查到数据了吗?查到了就登录成功
System.out.println("登录成功~");
}else{
System.out.println("用户名或者密码输入错误,登录失败~");
}
//6,关闭资源
r.close();
s.close();
c.close();
}
//查询tb_user表里的数据
private static void method() throws Exception{
//调用工具类的方法
Connection c = JDBCUtils.getConnection();
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
ResultSet r = s.executeQuery("select * from tb_user");
//5,解析结果集
while(r.next()){//判断r有数据
//获取r的数据
int a = r.getInt("id");//获取表里的id字段的值
String b = r.getString("name");//获取表里的name字段的值
String c1 = r.getString("password");//获取表里的password字段的值
System.out.println(a+b+c1);
}
//6,释放资源
r.close();//释放结果集
s.close();//释放传输器
c.close();//释放连接器
}
/* 模拟用户登录
1,发起SQL:select * from tb_user where name='jack' and password='321'
2,判断result,如果有结果就登录成功,没结果就登录失败
问题: SQL攻击/SQL注入,
本质上就是因为SQL语句中出现了特殊符号(#,注释掉了一些条件),导致了SQL语义改变了
解决方案:Statement低级的传输器,不安全,低效
换成PreparedStatement高级,安全
*/
private static void method2() throws Exception {
//1,注册驱动 2,获取连接
Connection c = JDBCUtils.getConnection();
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
String a = new Scanner(System.in).nextLine();//用户名
String b = new Scanner(System.in).nextLine();//密码
//如果动态的拼接字符串时,数据在中间的位置 "+a+"
// String sql="select * from tb_user where name='jack' and password='321'" ;
String sql="select * from tb_user where name='"+a+"' and password='"+b+"'" ;
ResultSet r = s.executeQuery(sql);
//5,解析结果集
if(r.next()){//查到数据了吗?查到了就登录成功
System.out.println("登录成功~");
}else{
System.out.println("用户名或者密码输入错误,登录失败~");
}
//6,关闭资源
r.close();
s.close();
c.close();
}
}
3.优化JDBC,SQL骨架
//JDBC的优化练习
public class JDBC2 {
public static void main(String[] args) throws Exception{
method();//查询部门表的<100数据
// method2();//向dept表里插入数据
}
//向dept表里插入数据
//为了资源一定会被释放?
// 把释放资源的代码放入finally里+扩大变量的作用范围
// +在try里修改变量的默认值null+在finally里进行try catch
private static void method2(){
//扩大变量的作用范围?因为想让finally也使用
Connection c = null ;
PreparedStatement p = null;
try{
c = JDBCUtils2.getConnection();
//插入数据时怎么决定要几个问号? 要看表里有几个字段需要设置值
String sql = "insert into dept values(?,?,?)" ;
p = c.prepareStatement(sql);
//设置SQL的参数
p.setObject(1,6);
p.setObject(2,"总部");
p.setObject(3,"上海");
//执行SQL
int rows = p.executeUpdate();//执行增删改的SQL
//TODO 会返回结果集吗?返回了的是啥?
System.out.println("影响的行数是: "+rows);
}catch (Exception e){
System.out.println("出错");
}finally {//资源的释放是一定要执行的
//关闭资源
JDBCUtils2.close(null,p,c);
}
}
//查询部门表的<100数据
private static void method() {
Connection c =null;
PreparedStatement s =null;
ResultSet r =null;
try{
c = JDBCUtils2.getConnection();//利用工具类,获取数据库的连接
//获取传输器,执行SQL骨架
String sql = "select * from dept where deptno < ?";
s = c.prepareStatement(sql);
//设置SQL的参数
s.setInt(1,100);//给第一个?设置100
r = s.executeQuery();//执行查询的SQL语句
//处理结果集
while(r.next()){//next()判断是否有下一个数据
int deptno = r.getInt("deptno");
String dname = r.getString("dname");
String loc = r.getString("loc");
System.out.println(deptno+dname+loc);
}
}catch (Exception e){
//项目上线阶段,给出的解决方案,比如输出
System.out.println("数据库连接出错");
//项目开发调试阶段,给出的解决方案,根据报错信息
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils2.close(r,s,c);
}
}
}