4.JDBC技术

一、JDBC概述
  1. JDBC:Java DataBase Connectivity Java连接数据库技术。

  2. JDBC四个接口一个类

    1. DriverManager:驱动管理器类,管理JDBC驱动,不同数据库驱动管理器不同
    2. Driver:驱动接口
    3. Connection:连接接口 传输数据
    4. Statement:由Connection创建,执行SQL接口
    5. 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();
    
  3. JDBC连接步骤

    1. 加载驱动
    2. 创建连接
    3. 编写sql
    4. 获取sql执行对象
    5. 执行sql并返回
    6. 关闭资源
二、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();
        }
    }

}
四、事务
  1. 事务的特点

    1. 原子性:一个事务,要么都提交,要么都回滚
    2. 一致性:事务必须是数据库从一个一致性状态变到另一个一致性状态
    3. 隔离性:事务之间互不影响
    4. 持续性:事务的结果可以被永久保留
  2. 事务的开始与结束

    1. 显示开始:执行DML
    2. 显式结束:执行commit,rollback
    3. 隐式提交:执行了DDL,DCL,exit
    4. 隐式回滚:系统异常,死机
  3. 事务中易出现的并发问题

    1. 脏读:读取到未提交的数据
    2. 不可重复读:同时读取数据时能读取到此时被修改的数据
    3. 幻读:同时读取数据时,读取到此时新增或删除的数据
  4. 事务的隔离级别

    1. 读未提交:可以读取到未提交的数据,脏读
    2. 读已提交:不能读取到未提交的数据,避免脏读
    3. 可重复读:同时访问数据时,禁止修改,避免不可重复读
    4. 串行化:同时访问数据时,禁止添加删除数据,避免幻读
  5. JDBC中的事务

    // 业务层增删改操作需要提交事务
    // 关闭自动提交
    connection.setAutoCommit(false);
    // 业务处理...
    // 业务处理后提交事务
    connection.Commit();
    
原文地址:https://www.cnblogs.com/forelim/p/14856155.html