JDBC入门-连接池-sql注入

197 阅读1分钟

JDBC全称Java DataBase Connectivity ( Java数据库连接 ),是Java语言操作数据库的一种技术。本质上是一个接口,具体的实现类由数据库厂商来实现

入门

编写一个jdbc文件

  1. 确保数据库已安装好
  2. 在模块中导入jar包
  3. 开写
public static void main(String[] args) throws SQLException, ClassNotFoundException {
    //1.注册驱动(指定是哪个数据库的jar)
    //Driver类中已经注册了一次驱动,所以会有驱动重复注册的问题,不建议使用
    //DriverManager.registerDriver(new Driver());
    //通过反射的方式加载Driver类
    Class.forName("com.mysql.jdbc.Driver");//建议使用,但是不使用也行,在后来的驱动版本中,通过url间接确认数据库

    //2.获取连接
    String url = "jdbc:mysql://localhost:3306/jdbc";
    String username = "root";
    String password = "root";
    //connection:数据库连接对象
    Connection connection = DriverManager.getConnection(url, username, password);

    //3.获取执行sql的对象
    Statement statement = connection.createStatement();

    //4.执行sql语句
    //executeUpdate用于执行增删改(DML)语句, 其返回结果是一个数字,代表sql对数据库的影响行数
    String sql = "insert into tbl_user values(null,'杨毅','123',3000)";
    int i = statement.executeUpdate("insert into tbl_user values(null,'杨毅','123',3000)");
    //executeQuery用于执行查询(DQL)语句, 其返回值是一个对象(数据的集合)
    ResultSet resultSet = statement.executeQuery("select * from tbl_user");

    //5.处理返回结果
    //executeUpdate结果
    System.out.println("处理了"+i+"条数据");
    //executeQuery结果
    List<User> list = new ArrayList<>();//创建集合保存用户数据
        while (resultSet.next()){//判断条件为是否有下一行,如果有,将指针移动到下一行
            //操作本行
            int id = resultSet.getInt("id");
            String name = resultSet.getNString("username");
            String pass = resultSet.getNString("password");
            int money = resultSet.getInt("money");
            //并封装成实体对象
            User user = new User(id, name, pass, money);
            //添加进集合
            list.add(user);
        }
        //打印
        System.out.println(list);
    //6.释放资源
    statement.close();
    connection.close();

}

jdbc事务+封装工具类

和sql中一样,一个事务中的一系列的操作要么全部成功,要么一个都不做。

MySQL中事务的相关方法

  • 开启事务: begin
  • 提交事务: commit
  • 回滚事务: rollback

JDBC中事务的相关方法

  • 开启事务: setAutoCommit(false)
  • 提交事务: commit()
  • 回滚事务: rollback()

工具类

package com.eponine.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class Jdbc_utils {
    static String url;
    static String username;
    static String password;
    static String driverClass;

    //静态代码块,仅在类被加载时运行一次,给成员变量赋值并且注册驱动
    static {
        //读取配置文件
        InputStream resourceAsStream = Jdbc_utils.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //给成员变量赋值
        url=properties.getProperty("url");
        username=properties.getProperty("username");
        password=properties.getProperty("password");
        driverClass=properties.getProperty("driverClass");
        //注册驱动(指定是哪个数据库的jar)
        //通过反射的方式加载Driver类
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        //获取连接
        Connection connection = DriverManager.getConnection(url, username, password);
        //由于mysql默认事务提交方式为自动,这里设置成手动,否则会报错
        connection.setAutoCommit(false);
        return connection;
    }
    //提交并关闭
    public static void commitAndClose(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if (resultSet!=null){
            resultSet.close();
        }
        if (statement!=null){
            statement.close();
        }
        if (connection!=null){
            connection.commit();
            connection.close();
        }
    }
    //回滚并关闭
    public static void rollbackAndClose(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if (resultSet!=null){
            resultSet.close();
        }
        if (statement!=null){
            statement.close();
        }
        if (connection!=null){
            connection.rollback();
            connection.close();
        }
    }
}

实体类

public static void main(String[] args) throws SQLException, ClassNotFoundException {

        //获取连接
        Connection connection = JDBCUtils03.getConnection();

        //查询id为2的用户信息
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("SELECT * FROM tbl_user WHERE id = 2");
        resultSet.next();
        int id = resultSet.getInt("id");
        String username1 = resultSet.getString("username");
        String password1 = resultSet.getString("password");
        int money = resultSet.getInt("money");
        TblUser user = new TblUser(id,username1,password1,money);
        System.out.println(user);

        //关闭资源
        JDBCUtils01.commitAndClose(connection,statement,resultSet);
    }

sql注入

  • 用户输入的内容作为了SQL语句语法的一部分,改变了原有 SQL真正的意义,这个问题称为SQL注入问题。
//sql注入数据 账号:随意   密码:abc' OR '1' ='1
ResultSet resultSet = statement.executeQuery("select * from tbl_user where username='杨晨'and password='abc' or '1'='1'");
  • 解决方法 预编译
        //编写一个带有占位符(?) 的SQL语句, 发往数据库编译
        String sql = "select * from tbl_user where username=?and password=?";
        //PreparedStatement表示预编译的SQL语句的对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //将参数传入
        preparedStatement.setString(1,"杨晨");
        preparedStatement.setString(2,"123456");

        //执行sql语句(增删改用executeUpdate,查用executeQuery)
        ResultSet resultSet = preparedStatement.executeQuery();

连接池

  • 连接池是一个容器,它会在程序初始化完毕之后, 创建一批Connection对象,维护在自身的容器中。这样的设计既可以节约资源,减轻服务器压力,也可以提高连接复用性。
  • 使用连接池(德鲁伊)
public static void main(String[] args) throws SQLException {
        //1.创建连接池
        DruidDataSource dataSource = new DruidDataSource();

        //设置参数 基本四项(必须设置)
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");//驱动
        dataSource.setUrl("jdbc:mysql://localhost:3306/jdbc");//连接
        dataSource.setUsername("root");//用户名
        dataSource.setPassword("root");//密码


        //其他的可选项
        dataSource.setMaxActive(10); //最大激活数
        dataSource.setInitialSize(3); //初始个数
        dataSource.setMaxWait(3000); //最大等待时间 单位毫秒

        //获得连接
        DruidPooledConnection connection = dataSource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("select * from tbl_user");

        //执行sql语句
        ResultSet resultSet = preparedStatement.executeQuery();

        //处理返回结果
        List<User> list = new ArrayList<>();
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            int money = resultSet.getInt("money");
            User user=new User(id,username,password,money);
            list.add(user);
        }
        System.out.println(list);
    }
  • 连接池工具类
//创建连接池
    private static DruidDataSource dataSource;

    static {
        InputStream resourceAsStream = DruidUtil.class.getClassLoader().getResourceAsStream("druidConfig.properties");
        Properties properties = new Properties();
        try {
            properties.load(resourceAsStream);
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() throws SQLException {

        //获得连接
        DruidPooledConnection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        return connection;
    }