📋 个人简介
- 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
 - 📝 个人主页:馆主阿牛🔥
 - 🎉 支持我:点赞👍+收藏⭐️+留言📝
 - 📣 系列专栏:java 小白到高手的蜕变🍁
 - 💬格言:要成为光,因为有怕黑的人!🔥

 
目录
- 📋 个人简介
 
- 前言
 - JDBC简介
 - JDBC快速入们
 - JDBC API 详解
 - DriverManager
 - Connection
 - Statement
 - ResultSet
 - PreparedStatement - SQL注入演示
 
- 结语
 
前言
一个项目肯定是离不开数据库的,每种语言都有涉及到操作数据库的内容,本节来看看java语言中如何使用JDBC如何操作数据库!
JDBC简介
就是使用java语言操作关系型数据库的一套API。
 
JDBC快速入们
主要有7步,当然在这之前肯定要先在当前项目或者模块中导入java操作mysql的jar包。对于这个jar包的下载不再总结!
 
 如图,在模块中新建一个libs目录,将这个jar包放到里面。然后我们要让这个模块识别这个jar包:
 
 
 我们选择模块有效就可以,然后就可以写代码了!
 这7步我注视到代码里:
package JdbcDemo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCDemo {
    public static void main(String[] args){
        try {
            methods();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void methods() throws Exception{
        // 1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
        String name = "root";
        String password = "...";
        Connection conn = DriverManager.getConnection(url,name,password);
        // 3.定义sql
        String sql = "update spj set QTY = 400 where SNO = 'S1'";
        // 4.获取执行sql的对象Statement
        Statement stmt = conn.createStatement();
        // 5. 执行sql
        int count = stmt.executeUpdate(sql); //返回更新的数据条数
        // 6.输出执行结果
        System.out.println("受影响行数:" + count);
        // 7.释放资源
        stmt.close();  //关闭执行sql的对象
        conn.close(); //关闭连接
    }
}
 

JDBC API 详解
DriverManager
DriverManager (驱动管理类)作用:
- 注册驱动
 - 获取数据库的连接
 

 但是,我们上面的案例代码中,并没有使用registerDriver来注册驱动,而是使用反射的方式加载Driver类,这个类里面用到了这个方法,来看看源码:
 
 当然,mysql 5.0之后的jar包,注册驱动的这行代码可以不用写了:
Class.forName("com.mysql.cj.jdbc.Driver");
 
因为这个jar包中有文件记录了这个类名,会读取文件自动加载!
 
Connection
Connection的参数说明:
 
 Connection(数据库连接对象)作用
- 获取执行sql的对象
 

- 管理事务
 

package Demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
 * @Author:Aniu
 * @Date:2023/2/26 14:16
 * @description TODO
 */
public class Demo {
        public static void main(String[] args){
            try {
                methods();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static void methods() throws Exception{
            // 1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
            String name = "root";
            String password = "...";
            Connection conn = DriverManager.getConnection(url,name,password);
            // 3.定义sql
            String sql1 = "update spj set QTY = 450 where SNO = 'S1'";
            String sql2 = "update spj set QTY = 250 where SNO = 'S2'";
            // 4.获取执行sql的对象Statement
            Statement stmt = conn.createStatement();
            try {
                // 开启事务
                conn.setAutoCommit(false);
                // 5. 执行sql
                int count1 = stmt.executeUpdate(sql1); //返回更新的数据条数
                // 6.输出执行结果
                System.out.println("受影响行数:" + count1);
                // 5. 执行sql
                int count2 = stmt.executeUpdate(sql2); //返回更新的数据条数
                // 6.输出执行结果
                System.out.println("受影响行数:" + count2);
                // 提交事务
                conn.commit();
            } catch (Exception e) {
                // 回滚事务
                conn.rollback();
                e.printStackTrace();
            }
            // 7.释放资源
            stmt.close();  //关闭执行sql的对象
            conn.close(); //关闭连接
        }
}
 

 开启事务的目的就是当发生异常的时候回滚,让这几条sql操作都不执行,这里不再多说!
Statement
Statement 的作用
- 执行sql操作

 
ResultSet
ResultSet (结果集对象)作用
 1.封装了DQL查询语句的结果
ResultSet stmt.execute(sql)  //执行DQL语句,返回ResultSet对象
 

 
 例:
package Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
 * @Author:Aniu
 * @Date:2023/2/26 14:50
 * @description ResultSet
 */
public class Test {
    public static void main(String[] args) throws Exception {
        // 1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
        String name = "root";
        String password = "...";
        Connection conn = DriverManager.getConnection(url,name,password);
        // 3.定义sql
        String sql = "select * from spj";
        // 4.获取Statement对象
        Statement stmt = conn.createStatement();
        // 5.执行sql
        ResultSet rs = stmt.executeQuery(sql);
        // 6.处理结果,遍历rs中的所有数据
        while(rs.next()){
            String sno = rs.getString("SNO");
            String pno = rs.getString("PNO");
            String jno = rs.getString("JNO");
            int qty = rs.getInt("QTY");
            System.out.println(sno);
            System.out.println(pno);
            System.out.println(jno);
            System.out.println(qty);
            System.out.println("------------");
        }
        // 7.释放资源
        rs.close();
        stmt.close();  //关闭执行sql的对象
        conn.close(); //关闭连接
    }
}
 

PreparedStatement - SQL注入演示
PreparedStatement 作用:
- 预编译SQL语句并执行:预防SQL注入问题
 
SQL注入
- SQL注入是通过操作输入来修改事先定义的SQL语句,用以达到执行代码对服务器进行攻击的方法。
 
进行这个案例,我们要先创建一张用户表:
CREATE TABLE `user` (
  `uid` bigint NOT NULL AUTO_INCREMENT COMMENT '用户uid', 
  `login_name` varchar(20) NOT NULL COMMENT '登录用户名',
  `login_pwd` varchar(32) NOT NULL COMMENT '登录密码',
   PRIMARY KEY (`uid`)
) 
 

package Login;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
 * @Author:Aniu
 * @Date:2023/2/26 15:36
 * @description TODO
 */
public class UserLogin {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
        String name = "root";
        String password = "...";
        Connection conn = DriverManager.getConnection(url,name,password);
        // 模拟用户输入的值
        String login_name = "aniu";
        String login_pwd = "123456";
        String sql = "select * from user where login_name = '" + login_name + "' and login_pwd = '" + login_pwd + "'";
        System.out.println(sql);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        // 判断是否登录成功
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
    }
}
 

 现在我们模拟sql注入,即使密码错误也可以登录成功!
public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
        String name = "root";
        String password = "...";
        Connection conn = DriverManager.getConnection(url,name,password);
        // 模拟用户输入的值(演示sql注入,用户名和密码随便写)
        String login_name = "aniu666";
        String login_pwd = "' or '1' = '1";
        String sql = "select * from user where login_name = '" + login_name + "' and login_pwd = '" + login_pwd + "'";
        System.out.println(sql);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        // 判断是否登录成功
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
        // 释放资源
        rs.close();
        stmt.close();  //关闭执行sql的对象
        conn.close(); //关闭连接
    }
 

 即使用户明和密码错误我们也可以登录,这是因为这个sql是恒等式所导致的!
那么怎么避免这个问题呢?就是通过这个PreparedStatement来解决!

public class UserLogin {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://127.0.0.1:3306/myclasswork";
        String name = "root";
        String password = "...";
        Connection conn = DriverManager.getConnection(url,name,password);
        // 模拟用户输入的值(演示sql注入,用户名和密码随便写)
        String login_name = "aniu666";
        String login_pwd = "' or '1' = '1";
        String sql = "select * from user where login_name = ? and login_pwd = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        // 设置?的值
        pstmt.setString(1,login_name);
        pstmt.setString(2,login_pwd);
        ResultSet rs = pstmt.executeQuery();
        // 判断是否登录成功
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
        // 7.释放资源
        rs.close();
        pstmt.close();  //关闭执行sql的对象
        conn.close(); //关闭连接
    }
}
 

 此时则显示登陆失败,避免了sql注入!本质上就是将sql中单引号进行了转义
 ’ \’ ',使用prepareStatement预编译sql性能更高!当然你要开启预编译,给Connection的url加参数:
String url = "jdbc:mysql://127.0.0.1:3306/myclasswork?useServerPrepStmts=true";
 
结语
如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。
🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门



















