JDBC学习

本文详细介绍了JDBC的概念、本质和好处,包括如何注册驱动、获取数据库连接,以及Statement、PreparedStatement和ResultSet等核心API的使用。同时,通过实例展示了事务管理和SQL注入问题,强调了PreparedStatement防止SQL注入的作用。最后,探讨了数据库连接池的概念、优点,并以Druid为例展示了连接池的配置和使用。
摘要由CSDN通过智能技术生成

一.JDBC简介

1.1JDBC概念

  • JDBC就是使用Java语言操作关系型数据库的一套API
  • 全称:(Java DataBase Connectivity) Java数据库连接

1.2JDBC本质

  • 官方(sum)公司定义的一套操作所有关系型数据库的规则,即接口
  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包

1.3JDBC好处

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变

在这里插入图片描述

二.JDBC快速入门

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;


/**
 * JDBC快速入门
 * */
public class Demo1 {
    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/sql_base";
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url,user,password);

        //3.定义sql
        String sql = "update account set money = 4000 where id = 1";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        //5.执行sql
        int count = statement.executeUpdate(sql);//返回值是受影响的条数

        //6.处理返回结果
        System.out.println(count);

        //7.释放资源 注意释放的先后顺序 先开后释放
        statement.close();
        con.close();
    }
}

此处使用的的MySQL数据库版本是mysql-5.7.30-winx64,驱动包是mysql-connector-java-8.0.29

三.JDBC的API详解

3.1DriverManager

作用:

  1. 注册驱动
  2. 获取数据库连接

获取连接方式

Connection con = DriverManager.getConnection(url,user,password);
        /**
         * url:连接路径
         * 语法:jdbc:mysql//ip地址:端口号/数据库名称?参数键值对1&参数键值对2
         * 细节:
         * 如果连接的是本机mysql,并且mysql服务器默认端口号是3306,则可以简写 jdbc:mysql///数据库名称?参数键值对
         * 配置useSSL=false参数,禁用安全连接方式,解决警告提示
         *
         * user:用户名
         * password:密码
         * */

3.2Connection

获取执行SQL对象

在这里插入图片描述

//4.获取sql执行对象 
Statement statement = con.createStatement();

事务管理

在这里插入图片描述

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;


/**
 * JDBC API详解 Connection
 * */
public class Demo3_Connection {
    public static void main(String[] args) throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");//反射 mysql5之后可以省略不写了

        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/sql_base";
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url,user,password);

        //3.定义sql
        String sql1 = "update account set money = 1000 where id = 1";
        String sql2 = "update account set money = 1000 where id = 2";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        try {
            //开启事务
            con.setAutoCommit(false);

            //5.执行sql
            int count1 = statement.executeUpdate(sql1);//返回值是受影响的条数
            int count2 = statement.executeUpdate(sql2);//返回值是受影响的条数
            //6.处理返回结果
            System.out.println(count1);
            System.out.println(count2);

            //提交事务
            con.commit();
        } catch (Exception e) {
            e.printStackTrace();

            //回滚事务
            con.rollback();
        }

        //7.释放资源 注意释放的先后顺序 先开后释放
        statement.close();
        con.close();
    }
}

3.3Statement

在这里插入图片描述

package jdbc;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;


/**
 * JDBC API详解 Statement
 * */
public class Demo4_Statement {


    /**
     * 执行DML语句
     * @throws SQLException
     */
    @Test
    public void testDML() throws SQLException {
        //1.注册驱动
//        Class.forName("com.mysql.cj.jdbc.Driver");//反射 mysql5之后可以省略不写了

        //2.获取连接
        String url = "jdbc:mysql:///sql_base?useSSL=false"; //本机服务器的ip和端口可以省略不写
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url,user,password);

        //3.定义sql
        String sql = "update account set money = 4000 where id = 5";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        //5.执行sql
        int count = statement.executeUpdate(sql);//执行完DML语句后,受影响的行数


        //6.处理返回结果
//        System.out.println(count);

        if(count > 0){
            System.out.println("修改成功");
        } else {
            System.out.println("修改失败");
        }
        //7.释放资源 注意释放的先后顺序 先开后释放
        statement.close();
        con.close();
    }


    /**
     * 执行DDL语句
     * @throws SQLException
     */
    @Test
    public void testDDL() throws SQLException {
        //1.注册驱动
//        Class.forName("com.mysql.cj.jdbc.Driver");//反射 mysql5之后可以省略不写了

        //2.获取连接
        String url = "jdbc:mysql:///sql_base?useSSL=false"; //本机服务器的ip和端口可以省略不写
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url,user,password);

        //3.定义sql
        String sql = "drop database db2";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        //5.执行sql
        int count = statement.executeUpdate(sql);//执行完DML语句后,受影响的行数


        //6.处理返回结果
        System.out.println(count);//成功执行完DDL,结果可能返回零

//        if(count > 0){
//            System.out.println("修改成功");
//        } else {
//            System.out.println("修改失败");
//        }
        //7.释放资源 注意释放的先后顺序 先开后释放
        statement.close();
        con.close();
    }
}

注意 @Test 需要导入 import org.junit.Test;

3.4ResutlSet

在这里插入图片描述

在这里插入图片描述

package pojo;

public class Account {
    private int id;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

package jdbc;

import org.junit.Test;
import pojo.Account;

import java.sql.*;
import java.util.ArrayList;


/**
 * JDBC API详解 ResultSet
 */
public class Demo5_ResultSet {

    /**
     * ResultSet
     *
     * @throws SQLException
     */
    @Test
    public void testResultSet() throws SQLException {
        //1.注册驱动
//        Class.forName("com.mysql.cj.jdbc.Driver");//反射 mysql5之后可以省略不写了

        //2.获取连接
        String url = "jdbc:mysql:///sql_base?useSSL=false"; //本机服务器的ip和端口可以省略不写
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url, user, password);

        //3.定义sql
        String sql = "select * from account";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        //5.执行sql
//        statement.executeUpdate("insert into account values (3,'王五',2000)");
        ResultSet rs = statement.executeQuery(sql);


        //6.处理数据
//        while (rs.next()) {
//            int id = rs.getInt(1);
//            String name = rs.getString(2);
//            double money = rs.getDouble(3);
//
//            System.out.println(id);
//            System.out.println(name);
//            System.out.println(money);
//
//            System.out.println("---------------------------------");
//
//        }

        while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("---------------------------------");

        }

        //7.关闭资源
        rs.close();
        statement.close();
        con.close();
    }






    @Test
    public void testResultSet2() throws SQLException {
        //1.注册驱动
//        Class.forName("com.mysql.cj.jdbc.Driver");//反射 mysql5之后可以省略不写了

        //2.获取连接
        String url = "jdbc:mysql:///sql_base?useSSL=false"; //本机服务器的ip和端口可以省略不写
        String user = "root";
        String password = "123456";
        Connection con = DriverManager.getConnection(url, user, password);

        //3.定义sql
        String sql = "select * from account";

        //4.获取sql执行对象
        Statement statement = con.createStatement();

        //5.执行sql
        ResultSet rs = statement.executeQuery(sql);


        //6.处理数据
        ArrayList<Account> list = new ArrayList<>();
        while (rs.next()) {

            Account account = new Account();

            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            account.setId(id);
            account.setName(name);
            account.setMoney(money);

            list.add(account);
        }

        System.out.println(list);

        //7.关闭资源
        rs.close();
        statement.close();
        con.close();
    }
}

3.5PreparedStatement

在这里插入图片描述

普通登录演示

    /**
     * 演示普通登录操作
     * @throws SQLException
     */
    @Test
    public void testLogin() throws SQLException {
        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/sql_base";
        String user = "root";
        String password = "123456";

        Connection con = DriverManager.getConnection(url,user,password);

        //获取sql对象
        Statement statement = con.createStatement();


        //获得用户输入的账号和密码
        String name = "张三";
        String psw = "124";

        //sql执行语句
        String sql = "select * from user where name='"+name+"' and password='"+psw+"'";

        ResultSet rs = statement.executeQuery(sql);

        //处理数据
        if(rs.next()){
            System.out.println("登录成功");
        } else {
            System.out.println("登陆失败");
        }

        //7.释放资源 注意释放的先后顺序 先开后释放
        rs.close();
        statement.close();
        con.close();
    }

SQL注入

    /**
     * 演示SQL注入
     * @throws SQLException
     */
    @Test
    public void testLogin_Inject() throws SQLException {
        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/sql_base";
        String user = "root";
        String password = "123456";

        Connection con = DriverManager.getConnection(url,user,password);

        //获取sql对象
        Statement statement = con.createStatement();


        //获得用户输入的账号和密码
        String name = "wslahlghh";
//        String psw = "124";
        String psw = "' or '1' = '1 ";

        //sql执行语句
        String sql = "select * from user where name='"+name+"' and password='"+psw+"'";

        ResultSet rs = statement.executeQuery(sql);

        //处理数据
        if(rs.next()){
            System.out.println("登录成功");
        } else {
            System.out.println("登陆失败");
        }

        //7.释放资源 注意释放的先后顺序 先开后释放
        rs.close();
        statement.close();
        con.close();
    }

原因:

在sql字符串的拼接过程中 sql被修改了

select * from user where name='wslahlghh' and password='' or '1' = '1'
-- 被修改的sql语句where条件恒成立

PreparedStatement作用
在这里插入图片描述

    /**
     * 演示PreparedStatement
     * @throws SQLException
     */
    @Test
    public void testPreparedStatement() throws SQLException {
        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/sql_base";
        String user = "root";
        String password = "123456";

        Connection con = DriverManager.getConnection(url,user,password);

        //sql语句
        String sql = "select * from user where name = ? and password = ?";

        //获取用户输入的账号和密码
        String name = "张三";
        String pas = "123";

        //获取sql执行对象
        PreparedStatement preparedStatement = con.prepareStatement(sql);

        //?号替换
        preparedStatement.setString(1,name);
        preparedStatement.setString(2,pas);

        //执行sql语句
        ResultSet rs = preparedStatement.executeQuery();
  
        //处理数据
        if(rs.next()){
            System.out.println("登录成功");
        } else {
            System.out.println("登陆失败");
        }

        System.out.println(sql);
        //7.释放资源 注意释放的先后顺序 先开后释放
        rs.close();
        preparedStatement.close();
        con.close();
    }

PreparedStatement原理
在这里插入图片描述

    /**
     * 演示PreparedStatement原理
     * @throws SQLException
     */
    @Test
    public void testPreparedStatement2() throws SQLException {
        //2.获取连接
        String url = "jdbc:mysql:///sql_base?useServerPrepStmts=true";//开启预处理
        String user = "root";
        String password = "123456";

        Connection con = DriverManager.getConnection(url,user,password);

        //sql语句
        String sql = "select * from user where name = ? and password = ?";//预处理只需要做一次 每次采用相同模板 性能更高

        //获取用户输入的账号和密码
        String name = "张三";
        String pas = "123";


        //获取sql执行对象
        PreparedStatement preparedStatement = con.prepareStatement(sql);

        //?号替换
        preparedStatement.setString(1,name);
        preparedStatement.setString(2,pas);

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

        //处理数据
        if(rs.next()){
            System.out.println("登录成功");
        } else {
            System.out.println("登陆失败");
        }

        System.out.println(sql);
        //7.释放资源 注意释放的先后顺序 先开后释放
        rs.close();
        preparedStatement.close();
        con.close();
    }

日志文件的配置

log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2

四.数据库连接池

简介

  • 数据库连接池是个容器,负责分配,管理数据库连接

  • 它允许应用程序重复使用一个现有的数据库连接,而不是重新建立

  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库来连接而引起的数据库连接遗漏

  • 好处:

    资源重复利用

    提升系统相应速度

    避免数据库连接遗漏

数据库实现

标准接口:DataSource

常见的数据库连接池:DBCP C3P0 Druid

package druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //1.导入jar包

        //2.定于配置文件

        //3.加载配置文件
        Properties prop = new Properties();

        prop.load(new FileInputStream("jdbc-dome/src/druid.properties"));

        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5.获取数据库连接 Connection
        Connection con = dataSource.getConnection();

        System.out.println(con);

        System.out.println(System.getProperty("user.dir"));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值