05、JavaWeb启程——JDBC详解

news2024/11/19 14:35:50

1、JDBC概述

1、持久化概述

【简介】: 持久化指的是把内存中的数据存储到可掉电存储设备中以供之后使用。

2、JDBC概述

【简介】: JDBC是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一的访问。

【JDBC本质】: 其实就是Java官方提供的一套规范,帮助开发人员快速实现不同关系型数据库的连接。

【图解JDBC作用】:
在这里插入图片描述
在这里插入图片描述

2、JDBC快速入门

1、环境准备

  • 拷贝 MySQL 的 JDBC 驱动,到 Java 项目中: mysql-connector-java-5.1.26-bin.jar
  • 注意: 是 jar 包,不是 zip 包.
  • 选择 jar,把 jar 引用到 classpath 路径.idea 项目中创建一个目录 lib右键 lib 目录,点 Add as Library

2、JDBC开发流程

  • 加载数据库驱动
  • 获取连接对象
  • 创建获取语句对象
  • 执行SQL语句
  • 释放资源

3、JDBC快速入门

1、创建数据库和表

CREATE DATABASE demo;
CREATE TABLE t_student(
id BIGINT PRIMARY KEY AUTO_INCREMENT, 
name VARCHAR(20), 
age INT,
email VARCHAR(20)
);

2、完成插入功能

public class JdbcInsert {
    public static void main(String[] args) {
        try {
        // 1、加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2、获取数据库连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "admin");
            // 3、创建语句对象
            Statement statement=connection.createStatement();
            // 4、执行sql
            String sql="INSERT INTO student(name,age,email)VALUES('张三',18,'15651321@qq.com')";
            statement.execute(sql);
            // 5、释放资源
            statement.close();
            connection.close();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
}

3、JDBC功能类详解

1、DriverManager类

【DriverManager】: 驱动管理对象,主要用于加载注册关系型数据库的Driver类以及获取关系型数据库的连接对象。

【加载数据库驱动】:

  • 注册给定的数据库驱动对象:
public static void registerDriver(java.sql.Driver driver)
        throws SQLException {
        registerDriver(driver, null);
    }
  • 获取连接对象
/**
* 参数:
* url:指定连接某一个数据库的路径
* username:连接数据库的账号
* password:连接数据库的密码
**/
    public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();
        if (user != null) {
            info.put("user", user);
        }
        if (password != null) {
            info.put("password", password);
        }
        return (getConnection(url, info, Reflection.getCallerClass()));
    }

2、Connection类

【简介】: 关系型数据库连接对象,相当于Java程序和数据的通信桥梁。

【获取执行语句对象】:

  • 获取静态语句执行对象:
Statement createStatement() throws SQLException;
  • 获取预编译语句执行对象:
PreparedStatement prepareStatement(String sql) throws SQLException;

3、Statement类

【简介】: 静态SQL语句执行对象,用于执行字符串的SQL语句。

  • 执行DML/DDL语句:
/**
* 返回值:受影响行数
* 参数:insert、update、delete、create语句
*/
int executeUpdate(String sql) throws SQLException;
  • 执行DQL语句:
ResultSet executeQuery(String sql) throws SQLException;
  • 释放资源
// 关闭Statement对象
void close() throws SQLException;

4、DAO思想

1、DAO思想引入

在这里插入图片描述
没有dao的时候我们会存在大量的代码重复。

2、DAO介绍和方法设计

【简介】: DAO(数据库访问对象)是一个面向对象的数据库接口。将所有对数据源访问操作抽象封装在一个公共API中。

【设计图解】:
在这里插入图片描述

3、DAO开发规范

【命名规范】:

  • DAO 接口 : 表示对某个模型的 CRUD 操作做规范,以 I 开头,interface
    • 标准:IXxxDAO
    • 例: IEmployeeDAO/IStudentDAO
  • DAO 实现类: 表示对某个 DAO 接口的实现
    • 标准:XxxDAOImpl
    • 例:EmployeeDAOImpl/StudentDAOImpl
  • DAO 测试类: 测试 DAO 组件中的所有方法
    • 标准:XxxDAOTest: XxxDAO 组件的测试类,
    • 例:EmployeeDAOTest,StudentDAOTest

4、根据DAO规范搭建项目

  1. 创建项目
  2. 导入数据库驱动包
  3. 创建表和模型包以及模型对象 (domain/Student)
package cn.simplelife.daodemo.domain;

import lombok.*;

import java.math.BigDecimal;

/**
 * @ClassName Student
 * @Description
 * @Author simplelife
 * @Date 2022/10/3 18:21
 * @Version 1.0
 */

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Student {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  1. 创建 DAO 包和 DAO 接口,设计 DAO 接口方法 (dao/IStudentDAO)
package cn.simplelife.daodemo.dao;

import cn.simplelife.daodemo.domain.Student;

import java.util.List;

/**
 * @ClassName IStudentDao
 * @Description
 * @Author simplelife
 * @Date 2022/10/3 18:25
 * @Version 1.0
 */

public interface IStudentDAO {
    /**
     * 插入一个学生信息
     * @param student 要插入的学生信息
     */
    void insert(Student student);

    /**
     * 根据id删除一个学生信息
     * @param id 要删除的学生id
     */
    void delete(Long id);

    /**
     * 根据学生id修改学生id
     * @param student 要修改学生的id和新的信息
     */
    void update(Student student);

    /**
     * 根据学生的id查询学生的信息
     * @param id 要查询的学生id
     * @return 返回一个学生信息
     */
    Student selectOne(Long id);

    /**
     * 查询所有的学生信息
     * @return 返回所有的学生信息列表
     */
    List<Student> selectList();
}

  1. 创建 DAO 实现包,实现 DAO 接口(dao.impl/StudentDAOImpl)
package cn.simplelife.daodemo.dao.impl;

import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.domain.Student;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName StudentDaoImpl
 * @Description
 * @Author simplelife
 * @Date 2022/10/3 18:24
 * @Version 1.0
 */

public class StudentDAOImpl implements IStudentDAO {
    @Override
    public void insert(Student student) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getName());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getEmail());
            preparedStatement.execute();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void delete(Long id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "DELETE FROM student WHERE id=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setLong(1, id);
            preparedStatement.execute();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void update(Student student) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "UPDATE student SET name=?, age=?, email=? WHERE id=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getName());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getEmail());
            preparedStatement.setLong(4, student.getId());
            preparedStatement.execute();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Student selectOne(Long id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Student student = new Student();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "SELECT * FROM student WHERE id=?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setLong(1, id);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                long resultId = resultSet.getLong("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String email = resultSet.getString("email");
                student.setId(resultId);
                student.setName(name);
                student.setAge(age);
                student.setEmail(email);
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return student;
    }

    @Override
    public List<Student> selectList() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Student> list = new ArrayList<>();
        Student student = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "SELECT * FROM student";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                long resultId = resultSet.getLong("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String email = resultSet.getString("email");
                student = new Student(resultId, name, age, email);
                list.add(student);
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }
}

  1. 创建测试目录,生成测试类和方法(test/StudentDAOTest)
package cn.simplelife.daodemo.test;

import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.dao.impl.StudentDAOImpl;
import cn.simplelife.daodemo.domain.Student;
import org.junit.Test;

import java.util.List;

/**
 * @ClassName StudentDAOTest
 * @Description
 * @Author simplelife
 * @Date 2022/10/3 18:40
 * @Version 1.0
 */

public class StudentDAOTest {
    private IStudentDAO studentDAO = new StudentDAOImpl();

    @Test
    public void insert() {
        studentDAO.insert(new Student(null, "王五", 52, "6521@qq.com"));
    }

    @Test
    public void delete() {
        studentDAO.delete(2L);
    }

    @Test
    public void update() {
        Student student = new Student();
        student.setId(4L);
        student.setName("李四");
        student.setAge(18);
        student.setEmail("156321@qq.com");
        studentDAO.update(student);
    }

    @Test
    public void selectOne() {
        Student student = studentDAO.selectOne(4L);
        System.out.println(student);
    }

    @Test
    public void selectList() {
        List<Student> students = studentDAO.selectList();
        System.out.println(students);
    }
}

5、预编译语句对象

1、预编译语句对象简介

【简介】: PrepareStatement接口:是Statement接口的子接口,享有Statement中的方法。使用预编译语句对象,sql语句中使用?做占位符。

2、API详解

  • Connection API:
 PreparedStatement conn对象的.prepareStatement(String sql);
  • PreparedStatement API:
//设置第几个占位符的真正参数值. Xxx 表示数据类型,比如 String,int,long,Date等.
void setXxx(int parameterIndex,Xxx value); 

//设置第几个占位符的真正参数值.
void setObject(int parameterIndex, Object x); 

//执行DDL/DML语句. 注意:没有参数 // 若当前 SQL是 DDL语句,则返回 0.// 若当前 SQL是 DML语句,则返回受影响的行数.
int executeUpdate(); 

//执行DQL语句,返回结果集.
ResultSet executeQuery(); 

//释放资源
close(); 

【举例】:

public void insert(Student student) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");
            String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getName());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getEmail());
            preparedStatement.execute();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

6、重构设计

1、抽取JDBCUtil工具类

package cn.simplelife.homework.utils;

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

/**
 * 与操作数据库相关的工具
 */
public class JDBCUtils {
    /**
     * 私有化构造器防止外部创建对象
     */
    private JDBCUtils() {
    }

    /**
     * 私有化静态的Properties对象
     */
    private static Properties properties;

    static {
        // 1、获取类加载器
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        // 2、获取文件并将其转为输入流
        InputStream resourceAsStream = contextClassLoader.getResourceAsStream("db.properties");
        try {
            // 3、判断输入流是否为空
            if (resourceAsStream != null) {
                // 4、加载流文件
                properties = new Properties();
                properties.load(resourceAsStream);
            }
            // 5、加载数据库驱动
            Class.forName(properties.getProperty("driverClassName"));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接对象
     *
     * @return 返回获取的连接对象
     */
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 关闭资源
     *
     * @param connection 关闭获取的连接
     * @param statement  关闭静态sql执行资源
     * @param resultSet  关闭结果集资源
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2、抽取db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????

7、JDBC事务操作

【简介】: 事务是指将一组操作括为一个单元,为确保数据库中数据的一致性,数据操作是成组的单元,当单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

1、事务的属性

  • 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性:保证数据的完整性. 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
  • 隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

2、事务操作步骤

  • 定义开始一个事务,然后对数据进行修改操作。
  • 执行过程中如果没有问题就提交事务,此时修改将会被永久的保存起来。
  • 如果在执行过程中发生异常,回滚事务,数据库管理系统会将放弃您的所有的修改而回到开始事务的状态。

3、操作事务的模板

try{
//取消事务自动提交机制,设置为手动提交
connection对象.setAutoCommit(false);
//操作1
//操作2
//异常
//操作3
//....
//所有操作成功则 手动提交事务
connection对象.commit();
}catch(Exception e){
//处理异常
//出现异常 回滚事务
connection对象.rollback();
}

4、事务举例

  • Account类
package cn.simplelife.work.domain;

import lombok.*;

import java.math.BigDecimal;

/**
 * @ClassName Account
 * @Description
 * @Author simplelife
 * @Date 2022/10/4 20:16
 * @Version 1.0
 */
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Account {
    private Long id;
    private String name;
    private BigDecimal balance;
}

  • IAccountDAO接口
package cn.simplelife.work.dao;

import cn.simplelife.work.domain.Account;

import java.math.BigDecimal;

/**
 * @ClassName IAccountDAO
 * @Description
 * @Author simplelife
 * @Date 2022/10/4 20:38
 * @Version 1.0
 */

public interface IAccountDAO {
    /**
     * 转账
     *
     * @param sourceAccount 源账户
     * @param targetAccount 目标账户
     * @param money         转账金额
     */
    void transfer(Account sourceAccount, Account targetAccount, BigDecimal money);
}

  • IAccountDAOImpl实现类
package cn.simplelife.work.dao.Impl;

import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.JDBCUtils;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @ClassName IAccountDAOImpl
 * @Description
 * @Author simplelife
 * @Date 2022/10/4 20:43
 * @Version 1.0
 */

public class IAccountDAOImpl implements IAccountDAO {
    @Override
    public void transfer(Account sourceAccount, Account targetAccount, BigDecimal money) {
        Connection connection = JDBCUtils.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            if (connection != null) {
                // 1、判断是否有足够的余额
                String sql = "SELECT * FROM account WHERE id=? AND balance>=1000";
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setLong(1, sourceAccount.getId());
                resultSet = preparedStatement.executeQuery();
                // 2、余额不足开启提醒
                if (!resultSet.next()) {
                    System.out.println("账户余额不足!请充值!");
                    return;
                }
                // 3、余额充足开始转账
                sql = "UPDATE account SET balance = balance-? WHERE id=?";
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setBigDecimal(1, money);
                preparedStatement.setLong(2, sourceAccount.getId());
                preparedStatement.executeUpdate();
                // 模拟停电
                int i = 10 / 0;
                // 4、账户价钱
                sql = "UPDATE account SET balance = balance+? WHERE id=?";
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setBigDecimal(1, money);
                preparedStatement.setLong(2, targetAccount.getId());
                preparedStatement.executeUpdate();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection, preparedStatement, resultSet);
        }
    }
}

  • 测试类
package cn.simplelife.work.dao.test;

import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.dao.Impl.IAccountDAOImpl;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.DataSourceUtils;
import org.junit.Test;

import java.math.BigDecimal;
import java.sql.Connection;

import static org.junit.Assert.*;

/**
 * @ClassName IAccountDAOImplTest
 * @Description
 * @Author simplelife
 * @Date 2022/10/4 21:15
 * @Version 1.0
 */

public class IAccountDAOImplTest {
    private IAccountDAO accountDAO = new IAccountDAOImpl();

    @Test
    public void transfer() {
        Account sourceAccount = new Account();
        Account targetAccount = new Account();
        sourceAccount.setId(1L);
        targetAccount.setId(2L);
        accountDAO.transfer(sourceAccount, targetAccount, new BigDecimal("1000"));
    }
}

5、事务使用注意事项

  • 默认情况下,事务在执行完DML操作之后就会自动提交。
  • 查询操作实际上不需要事务,但是,我们在开发中都把查询放入事务中。
  • 开发中,代码完全正确,没有异常,但是数据库中数据没有变化,可能是没有提交事务。
  • 在 MySQL 中,只有 InnoDB 存储引擎支持事务,支持外键,MyISAM 不支持事务。

8、SQL注入详解

1、Statement 和 PreparedStatement 的区别

  • PreparedStatement 具有更好的可读性,可维护性。
  • PreparedStatement 可以提供更好的性能。Mysql不支持PreparedStatement 性能优化。
  • PreparedStatement 更安全可以防止sql注入。

9、连接池思想

1、连接池引入和介绍

【简介】: 普通的 JDBC 数据库连接(Connectiond对象)使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码得花费 0.05s~1s 的时间, 时间成本比较大 。

【图解】:
在这里插入图片描述
【基本属性】: 连接池存了连接对象,而连接对象依赖四要素,所以四要素是基本要求。

【其他属性】:

  • 初始化连接数:5 在连接池中事先准备好5个Connection对象
  • 最多连接数:10 在连接池中最多有10个Connection对象,其他客户端进入等待状态
  • 最少连接数 : 3 在连接池中最少存在3个Connection对象
  • 最长等待时间:5 min 使用5分钟来申请获取 Connection 对象,如果时间到还没有申请到,则提示,自
    动放弃
  • 最长超时时间:10min 如果你在10分钟之内没有任何动作,则认为是自动放弃 Connection 对象.

2、druid连接池的使用

  • 拷贝 jar: druid-1.0.15.jar
  • 抽取db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????
  • 创建工具类
package cn.simplelife.work.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @ClassName DataSourceUtils
 * @Description
 * @Author simplelife
 * @Date 2022/10/14 9:34
 * @Version 1.0
 */

public class DataSourceUtils {
    private DataSourceUtils() {
    }

    private static DataSource dataSource = null;

    static {
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties");
        try {
            if (resourceAsStream != null) {
                Properties properties = new Properties();
                properties.load(resourceAsStream);
                // 调用工厂中的方法创建连接池对象
                dataSource = DruidDataSourceFactory.createDataSource(properties);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接对象
     *
     * @return 返回一个数据库连接对象
     */
    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void close(Connection connection, Statement statement, ResultSet resultSet){
        if (resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/618.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】泛型

当你觉得这条路很难走的时候&#xff0c;一定是上坡路 目录 1.初识泛型 1.1 什么是泛型 1.2泛型类语法 1.2.1泛型类定义 1.2.2泛型类使用语法 1.2.3泛型类的使用 1.2.4裸类型 2.泛型如何编译 2.1擦除机制 3.泛型的上界 3.1语法 3.2示范 4.泛型方法 4.1 语法 …

i.MX 6ULL 驱动开发 十九:RGBLCD

一、RGBLCD 硬件原理 【正点原子MP157连载】第十八章 RGB LCD彩条显示实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7_正点原子的博客-CSDN博客 ATK7016 时序参数&#xff1a; 二、eLCDIF 接口 eLCDIF 是 I.MX6U 自带的液晶屏幕接口&#xff0c;用于连接 RGB …

【Linux】没有GDB,何谈Linux C

一、简单的开始 1、有C代码如下 #include <stdio.h>void main() {printf("Hello World!"); }2、通过gcc编译 生成带有调试信息的可运行程序&#xff0c;编译参数-g gcc -g hello.c -o hello3、运行GDB -q表示不打印gdb版本信息&#xff0c;界面较为干净 …

linux内核调试工具之kprobe

目录 一、内核调试的痛点 二、kprobe的优点 三、kprobe探测点的要点 四、探测点的开销与优化 五、内核配置 六、API 七、程序架构 八、实例 一、内核调试的痛点 内核调试&#xff0c;添加打印信息。在运行过程中想看某个函数的变量&#xff0c;需要重新编译内核。这样破…

【C语言】指针(进阶)

目录一、字符指针二、数组指针2.1、数组指针的定义2.2、&数组名和数组名2.3、数组指针的使用三、数组传参、指针传参3.1、一维数组传参3.2、二维数组传参3.3、一级指针传参3.4、二级指针传参四、函数指针五、函数指针数组六、指向函数指针数组的指针七、回调函数一、字符指…

【C语言小游戏】详解三子棋,深刻掌握二维数组

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#xff0c;今天带领大家实现一个C语言小游戏&#xff0c;主要运用的知识点为二维数组&#xff0c;希望这篇文章让大家对二维数组有更深刻的认识。 &#x1f49e;看似不起波澜的日复一日&#xff0c;会突然在某一天让人看到坚持…

【day14】【洛谷算法题】-P5711闰年判断-刷题反思集[入门2分支结构]

&#x1f338;大家好&#xff0c;我是花无缺&#xff0c;一枚热爱生活的新时代青年&#xff0c;感谢你的阅读&#x1f970;~ &#x1f468;‍&#x1f4bb;个人主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专…

PC - 史上最简单的远程访问群晖 NAS 方法

文章目录1、下载安装cpolar群晖套件1.1 注册cpolar账号1.2 下载cpolar群晖套件1.3 安装cpolar群晖套件2、创建隧道映射5000端口2.1 打开cpolar群晖套件2.2 创建远程访问隧道2.3 获取公网URL地址3、公网远程群晖NAS教大家一个新手小白都可以轻松掌握的远程群晖NAS方法&#xff0…

算法的时间复杂度和空间复杂度

文章目录算法的时间复杂度和空间复杂度算法效率算法的复杂度时间复杂度时间复杂度的概念大O的渐进表示法常见的时间复杂度计算举例空间复杂度常见复杂度对比复杂度的oj练习算法的时间复杂度和空间复杂度 算法效率时间复杂度空间复杂度常见的时间复杂度以及复杂度的oj练习 算法…

【题解】方格取数

&#x1f60a;博主目前也在学习&#xff0c;有错误欢迎指正&#x1f60a; &#x1f308;保持热爱 奔赴星海&#x1f308; 文章目录一、题目1、题目描述3、原题链接二、解题报告1、思路分析2、代码详解三、本题知识一、题目 1、题目描述 输入格式&#xff1a; 输入的第一行为一…

Java并发编程实战之互斥锁

文章目录Java并发编程实战之互斥锁如何解决原子性问题&#xff1f;锁模型Java synchronized 关键字Java synchronized 关键字 只能解决原子性问题&#xff1f;如何正确使用Java synchronized 关键字&#xff1f;锁和受保护资源的合理关联关系死锁预防死锁破坏占有且等待条件破坏…

字节一面:TCP 三次握手,问的好细!

大家好&#xff0c;我是小林。 有位读者在面试字节时&#xff0c;被问到这么个问题&#xff1a; 概括起来&#xff0c;是这两个问题&#xff1a; TCP 三次握手中&#xff0c;客户端收到的第二次握手中 ack 确认号不是自己期望的&#xff0c;会发生什么&#xff1f;是直接丢弃…

1024程序员节:从关注自身健康开始

今天是1024程序员节&#xff0c;我们已经历经了尽三年的疫情&#xff0c;健康是我们最应该关注的事情&#xff0c;在这个特别的日子里&#xff0c;希望程序员们都能更加爱惜自己的身体&#xff0c;少加班&#xff0c;多锻炼。 健身不仅是保持健康体魄的关键要素之一&#xff0c…

基于ssm高校科研管理系统-计算机毕业设计源码+LW文档

【摘 要】高校科研管理是一项重要而又繁琐的工作&#xff0c;有效的信息管理平台可以大大缓解科研管理压力&#xff0c;减少工作量。本文以石河子大学信息科学与技术学院为应用背景&#xff0c;开发教师教学信息与论文信息交流平台。该系统能对科研成果和课题进行较为全面的管理…

第十三届蓝桥杯C++B组国赛I题——齿轮 (AC)

目录1.齿轮1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.样例说明6.数据范围7.原题链接2.解题思路3.Ac_code1.齿轮 1.题目描述 这天, 小明在组装齿轮。 他一共有 nnn 个齿轮, 第 iii 个齿轮的半径为 rir_{i}ri​, 他需要把这 nnn 个齿轮按一定 顺序从左到右组装起来…

[附源码]Java计算机毕业设计SSM公司办公自动化系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

10个实用的CSS样式之悬浮卡片

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大三菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 &#x1f4da;订阅专栏&#xff1a;『10个实用的CSS样式』 10个实用的CSS样式之悬浮卡片1.简介2.布局设计3.样式美化3.1body美化3.2c…

隔离技术之端口隔离

端口隔离技术 端口隔离主要应用在同一个vlan内&#xff0c;不同的用户之间不可互相访问 好处&#xff1a; 可以避免广播风暴&#xff0c;节约了vlan的资源&#xff0c;提高了用户之间的安全性 比如一个用户的电脑中病毒了&#xff0c;不会影响到其他用户 端口隔离是基于端口&…

网络原理——No.2 传输层_TCP的连接管理(画图理解三次握手与四次挥手)

JavaEE传送门JavaEE 网络原理——传输层_UDP 网络原理——No.1 传输层_TCP的确认应答机制与超时重传 目录TCP的连接管理三次握手(建立连接)四次挥手(断开连接)TCP的连接管理 描述的就是 TCP 建立链接和断开链接的过程 TCP 的链接, 只是一个 “逻辑上的” “虚拟的连接” (只要…

qt学习笔记4:QMainWindow 菜单栏、工具栏、状态栏、铆接部件、

在创建基类的时候&#xff0c;有三大选择&#xff0c;一个是QWidge 空窗口&#xff0c; 另一个就是QMainWindow QMainWindow是一个为用户提供主窗口的类&#xff0c;包含一个菜单栏&#xff0c;多个工具栏&#xff0c;多个链接部件&#xff0c; 一个状态栏以及一个中心部件&…