4.JDBC技术
一、JDBC概述
- 
JDBC:Java DataBase Connectivity Java连接数据库技术。
 - 
JDBC四个接口一个类
- DriverManager:驱动管理器类,管理JDBC驱动,不同数据库驱动管理器不同
 - Driver:驱动接口
 - Connection:连接接口 传输数据
 - Statement:由Connection创建,执行SQL接口
 - ResultSet:保存Statement执行后产生的查询结果集接口
 
// java.sql.DriverManager类,获取并加载驱动 Class.forName("驱动连接"); MySQL5: "com.mysql.jdbc.Driver" MySQL8: "com.mysql.cj.jdbc.Driver" Oracle11g: "oracle.jdbc.driver.OracleDriver" // java.sql.Driver驱动接口// java.sql.Connection 获取连接,实现与数据库之间的连接 Connection conn = DriverManager.getConnection(数据库连接,用户名,密码); MySQL: "jdbc:mysql://localhost:3306/数据库名?useSSL=false&characterEncoding=utf-8&serverTimeZone=Asia/Shanghai" Oracle: "jdbc:oracle:thin:@localhost:1521:数据库实例名" // java.sql.Statement,java.sql.PreparedStatement 发送并执行SQL接口 // 1. 创建执行sql的对象 Statement statement = conn.createStatement(); // 2. 创建预编译对象 PreparedStatemnt preparedStatement = conn.prepareStatement(sql); // 3. 返回自增的键 仅在增加语句使用 PreparedStatemnt preparedStatement = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);// java.sql.ResultSet 获取查询的结果集 // 1. 执行sql返回结果集或操作的行数 ResultSet resultSet = statement.executeQuery(sql); int num = statement.executeUpdate(sql); // 2. 预编译对象已经执行过sql 返回结果集或操作的行数 ResultSet resultSet = preparedStatement.executeQuery(); int num = preparedStatement.executeUpdate(); // 3. 获取自增键的结果集 Result resultSet = preparedStatement.getGeneratedKeys(); - 
JDBC连接步骤
- 加载驱动
 - 创建连接
 - 编写sql
 - 获取sql执行对象
 - 执行sql并返回
 - 关闭资源
 
 
二、SQL注入
1. 概念:通过特殊参数传入程序,非法侵入系统
2. 解决方法:使用PreparedStatement创建对象
 - PreparedStatement批处理速度快,效率高,安全性高
 - PreparedStatement不使用字符串拼接,安全性高
 - 预编译SQL命令,无需多次创建对象,批处理速度快,效率高
 - Statement使用SQL拼接,执行一次编译一次,效率低,安全性低
三、封装Connection对象
# jdbc.properties
# DRIVER
driverClassName=com.mysql.cj.jdbc.Driver
# URL
url=jdbc:mysql://localhost:3308/goods?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
# USER
username=root
# PASSWORD
password=mysql
# 最大活跃数量
maxActive=50
# 最大空闲数量
maxIdle=20
# 最大等待时长
maxWait=60000
package com.goods.util;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
 * @program: jdbc_study
 * @description: MySQL工具类
 * @author: MaEnguang
 * @create: 2021-06-01 10:10
 **/
public class DBUtil {
    // 工具类 禁止外部实例化
    private DBUtil() {
    }
    // 声明一个配置文件类
    private static Properties properties = new Properties();
    // 创建数据源对象
    private static DataSource dataSource;
    static {
        try (
                // 获取文件流
                InputStream resourceAsStream = DBUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        ) {// 文件类加载文件流
            properties.load(resourceAsStream);
            // 创建数据源管理
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 处理多线程
    private static ThreadLocal<Connection> local = new ThreadLocal<>();
    /**
     * 获取连接
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        // 仅获取本地一条线程的连接
        Connection connection = local.get();
        if (connection == null || connection.isClosed()) {
            // 通过数据源管理连接
            connection = dataSource.getConnection();
            // 将数据源放到本地线程中 保证线程安全
            local.set(connection);
        }
        return connection;
    }
    /**
     * 关闭连接
     */
    public static void closeConnection() {
        try {
            // 仅获取本地一条线程的连接
            Connection connection = local.get();
            if (connection != null && !connection.isClosed()) {
                // 释放数据源中占用的连接
                connection.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 线程需要移除
            local.remove();
        }
    }
}
四、事务
- 
事务的特点
- 原子性:一个事务,要么都提交,要么都回滚
 - 一致性:事务必须是数据库从一个一致性状态变到另一个一致性状态
 - 隔离性:事务之间互不影响
 - 持续性:事务的结果可以被永久保留
 
 - 
事务的开始与结束
- 显示开始:执行DML
 - 显式结束:执行commit,rollback
 - 隐式提交:执行了DDL,DCL,exit
 - 隐式回滚:系统异常,死机
 
 - 
事务中易出现的并发问题
- 脏读:读取到未提交的数据
 - 不可重复读:同时读取数据时能读取到此时被修改的数据
 - 幻读:同时读取数据时,读取到此时新增或删除的数据
 
 - 
事务的隔离级别
- 读未提交:可以读取到未提交的数据,脏读
 - 读已提交:不能读取到未提交的数据,避免脏读
 - 可重复读:同时访问数据时,禁止修改,避免不可重复读
 - 串行化:同时访问数据时,禁止添加删除数据,避免幻读
 
 - 
JDBC中的事务
// 业务层增删改操作需要提交事务 // 关闭自动提交 connection.setAutoCommit(false); // 业务处理... // 业务处理后提交事务 connection.Commit(); 
                    
                
                
            
        
浙公网安备 33010602011771号