导航

JDBC学习

Posted on 2023-05-17 17:37  isrhino  阅读(12)  评论(0编辑  收藏  举报

JDBC访问数据库的步骤

  1. 导入sql包
  2. 加载并注册驱动程序
  3. 创建connection对象
  4. 创建statement对象
  5. 执行SQL语句
  6. 使用ResultSet对象获取SQL语句执行结果
  7. 关闭statement对象
  8. 关闭connection对象

读取properties文件

// 读取jdbc.properties
FileInputStream fileInputStream = new FileInputStream("src/jdbc.properties");
properties.load(fileInputStream);
fileInputStream.close();

// 获取其中信息
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");

PreparedStatement

防止SQL注入
处理Blob(binary large object)类型对象
比如图片

PreparedStatement preparedStatement = connection.prepareStatement("insert into user values (?, ?, ?)");

preparedStatement.setInt(1, 5);
preparedStatement.setString(2, "sss");
preparedStatement.setBlob(3, new FileInputStream("src/head/1.webp"));

int i = preparedStatement.executeUpdate();

DAO

员工和部门的增删改拆

数据库连接池

dbcp

配置文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://root@localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
user=root
password=123456
# 指定数据库连接池中初始化连接数的个数
initialSize=3
# 指定最大的连接数: 同一时刻可以同时向数据库申请的连接数
maxActive=5
# 在数据库连接池中保存的最少的空闲连接的数量
minIdle=2
# 等待数据库连接池分配连接的最长时间. 单位为毫秒. 超出该时间将抛出异常
maxWait=5000

读取配置文件

Properties properties = new Properties();

InputStream inputStream = new BufferedInputStream(new FileInputStream("src/dbcp.properties"));
properties.load(inputStream);

DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();

c3p0

相较于dbcp可以自动回收空闲连接

JDBC的一些操作(取得自动生成的主键、批处理、事务)

JDBC 取得数据库自动生成的主键

在增加一条数据后,不仅返回1或0来判断是否添加成功
还能返回增东生成的主键值
在增加数据时,注意自动生成的主键位置填写null
并且在后面添加 Statement.RETURN_GENERATED_KEYS
比如PreparedStatement preparedStatement = connection.prepareStatement("insert into user values (null, ?, ?)", Statement.RETURN_GENERATED_KEYS);
在获取时使用 PreparedStatement的getGeneratedKeys()方法获取ResultSet类型的值
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
最后再使用while循环遍历 generatedKeys 的值获取getObject(1)的主键值
System.out.println(generatedKeys.getObject(1));

批处理

比如在添加100个用户的时候,使用循环一个个添加,耗费时间比使用批处理添加的方式更长
addBatch() 添加要执行的语句
executeBatch() 批处理执行刚添加的语句

// 不使用批处理的添加
PreparedStatement preparedStatement = connection.prepareStatement("insert into user(id, name) values (null, ?)");
for (int i = 0; i < 100; i++) {

	preparedStatement.setString(1, "ye" + i);
	int i1 = preparedStatement.executeUpdate();

}

// 使用批处理的方式添加
PreparedStatement preparedStatement = connection.prepareStatement("insert into user(id, name) values (null, ?)");
for (int i = 300; i < 400; i++) {

	String name = "zhang" + i;
	preparedStatement.setString(1, name);
	preparedStatement.addBatch();

}
preparedStatement.executeBatch();

事务

和MySQL中的事务一样
需要先设置自动提交方式为false以开启事务
connection.setAutoCommit(false);
使用try-catch-finally,
在try中所有操作完成后添加connection.commit();
在catch中添加connection.rollback();,在出现异常后回滚
在finally中要设置自动提交方式为true
connection.setAutoCommit(true);

一些问题

访问时报错
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
当前MySQL版本是8.0.x,mysql-connector-java依赖包版本是5.1.x版本,版本太低,依赖包版本改成8.0.11就可以解决
依赖包版本更新后,url后面需要加入
?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
Class.forName("com.mysql.jdbc.Driver")要改成Class.forName("com.mysql.cj.jdbc.Driver")

JDBCUtils

JDBC访问数据库的步骤整体来看真正需要改动的也就SQL语句,其他的基本都是重复的,为解决在开发中需要反复编写其他步骤,编写一个JDBCUtils工具类将这些不需要改动的其他步骤封装起来,开发过程中调用起来更方便

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

public class JDBCUtils {

    private static String url;
    private static String user;
    private static String password;


    static {

        Properties properties = new Properties();
        try {

            // 读取配置文件中信息
            FileInputStream fileInputStream = new FileInputStream("src/jdbc.properties");
            properties.load(fileInputStream);
            fileInputStream.close();

            String driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");

            // 加载驱动
            Class.forName(driver);

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

    }



    // 创建connection对象建立连接
    static Connection getConnection() throws SQLException {

        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }

    static void closeConnection(Connection connection) {

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

    }

    static void closeStatement(Statement statement) {

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

        }

    }

    static void closeResultSet(ResultSet resultSet) {

        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

    }

    static void closeCUD(Statement statement, Connection connection) {

        closeStatement(statement);
        closeConnection(connection);

    }

    static void closeQuery(ResultSet resultSet, Statement statement, Connection connection) {

        closeResultSet(resultSet);
        closeStatement(statement);
        closeConnection(connection);

    }

}