package com.yj.utils;
// 声明包名

import com.alibaba.druid.pool.DruidDataSource;
// 导入Druid连接池的数据源类
import com.alibaba.druid.pool.DruidDataSourceFactory;
// 导入Druid连接池的工厂类
import com.alibaba.druid.util.JdbcUtils;
// 导入Druid的工具类（注意：此处的JdbcUtils并非JDK自带的，而是Druid框架提供的，但在此代码中未直接使用）

import java.io.InputStream;
// 导入输入流接口
import java.sql.Connection;
// 导入数据库连接接口
import java.sql.SQLException;
// 导入SQL异常类
import java.util.Properties;
// 导入属性类

/**
 * @author yj
 * @create 2020-08-21 10:48
 */
public class JDBCUtils {
    // 定义一个工具类
    private static DruidDataSource dataSource;
    // 定义一个静态的Druid数据源对象
    private static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();
    // 定义一个ThreadLocal对象，用于存储每个线程的数据库连接

    static {
        // 静态代码块，用于初始化静态变量
        try {
            Properties properties = new Properties();
            // 创建一个属性对象
            // 读取jdbc.properties属性配置文件
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            // 从流中加载数据到属性对象中
            properties.load(inputStream);
            // 创建数据库连接池
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
            // 使用Druid工厂类创建数据源对象

        } catch (Exception e) {
            // 捕获异常
            e.printStackTrace();
            // 打印异常堆栈信息
        }
    }

    /**
     * 获取数据库连接池的连接
     * @return 如果返回null则连接失败
     */
    public static Connection getConnection() {
        // 定义一个静态方法，用于获取数据库连接
        Connection conn = conns.get();
        // 从ThreadLocal对象中获取当前线程的连接
        if(conn == null) {
            // 如果当前线程没有连接
            try {
                conn = dataSource.getConnection();
                // 从数据库池中获取连接
                conns.set(conn);
                // 将连接保存到ThreadLocal对象中，供后面的JDBC操作使用
                conn.setAutoCommit(false);
                // 设置为手动管理事务
            } catch (SQLException throwables) {
                // 捕获SQL异常
                throwables.printStackTrace();
                // 打印异常堆栈信息
            }
        }
        return conn;
        // 返回连接
    }

    /**
     * 提交事务并关闭释放连接
     */
    public static void commitAndClose() {
        // 定义一个静态方法，用于提交事务并关闭连接
        Connection connection = conns.get();
        // 从ThreadLocal对象中获取连接
        if(connection!=null) {
            // 如果连接不为空
            try {
                connection.commit();// 提交事务
            } catch (SQLException throwables) {
                // 捕获SQL异常
                throwables.printStackTrace();
                // 打印异常堆栈信息
            }finally {
                try {
                    connection.close();
                    // 关闭连接释放资源
                } catch (SQLException throwables) {
                    // 捕获SQL异常
                    throwables.printStackTrace();
                    // 打印异常堆栈信息
                }
            }
        }
        // 移除ThreadLocal对象中的连接，防止内存泄漏（特别是在使用线程池时）
        conns.remove();
    }

    /**
     * 回滚事务并关闭释放连接
     */
    public static void rollbackAndClose() {
        // 定义一个静态方法，用于回滚事务并关闭连接
        Connection connection = conns.get();
        // 从ThreadLocal对象中获取连接
        if(connection!=null) {
            // 如果连接不为空
            try {
                connection.rollback();
                // 回滚事务
            } catch (SQLException throwables) {
                // 捕获SQL异常
                throwables.printStackTrace();
                // 打印异常堆栈信息
            }finally {
                try {
                    connection.close();
                    // 关闭连接释放资源
                } catch (SQLException throwables) {
                    // 捕获SQL异常
                    throwables.printStackTrace();
                    // 打印异常堆栈信息
                }
            }
        }
        // 移除ThreadLocal对象中的连接，防止内存泄漏（特别是在使用线程池时）
        conns.remove();
    }

    /*
        （注释掉的代码）关闭连接，放回数据库连接池
        （注意：由于使用了连接池，通常不需要手动关闭连接放回池中，连接池会自动管理连接的回收和重用）
    public static void close(Connection conn) {
        if(conn != null) {
            try {
                conn.close();
                 // 这里实际上并不是将连接关闭，而是将连接归还给连接池（对于连接池而言）
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }*/

}