JDBC学习笔记

简介

JDBC(Java DataBase Connectivity)是Java编程语言中连接数据库的一种标准规范, 其提供了访问许多不同类型数据库的标准化方法,使得Java程序员能够很容易地使用数据库和执行SQL查询,从而方便地与任何数据库进行交互。

  • 本质上JDBC就是用来操作关系型数据库的一套API。

JDBC API包含两个级别:

  • JDBC API:Java应用程序通过这个API与JDBC管理器通信。

  • JDBC 驱动程序API:这个API定义了Java应用程序和JDBC驱动程序之间的协议。

  • JDBC可以为所有主流数据库提供统一的访问方式,从而有助于加快Java开发者的工作效率。

下面是个使用java语言操作关系型数据库的一套API

导入jar

image-20230417225731159

image-20230417225839387

举例

public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc", "root", "12345678");
System.out.println("Connected to database successfully!");
} catch (ClassNotFoundException e) {
System.out.println("Error: unable to load driver class!");
e.printStackTrace();
} catch (SQLException e) {
System.out.println("Error: failed to connect to database!");
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}

image-20230417230155033

API详解

DriverManager

  • 驱动管理类1.注册驱动2.获取数据库连接
  • 与各种关系型数据库进行通信。

以下部分方法:

方法 解释
getConnection() 连接到指定的数据库,并返回一个连接对象
getDriver() 返回一个具体的驱动
setLogWriter() 设置当前应用程序的日志Writer对象
getLogWriter() 获取当前应用程序的日志Writer对象

Connection

  • 表示与特定的数据库进行连接。
  • 一旦获得一个Connection对象,就可以使用它来执行SQL语句。
方法 解释
createStatement() 创建一个 Statement 对象,用于执行静态 SQL 语句并返回其生成的结果。
prepareStatement(String sql) 创建一个 PreparedStatement 对象,用于将参数化的 SQL 语句发送到数据库。
setAutoCommit(boolean autoCommit) 设置是否启用自动提交模式。如果启用,每个 SQL 语句默认作为事务处理。
commit() 使自上次提交以来所做的所有更改成为永久性更改,并释放 Transaction 对象当前持有的所有锁。
rollback() 撤销自上次提交以来所做的所有更改,并释放 Transaction 对象当前持有的所有锁。
close() 关闭此 Connection 对象并释放与之关联的所有资源。

Statement

  • 能够执行静态的SQL语句,并返回产生结果。
  • 代表在数据库上执行的SQL语句的接口
方法名 解释
executeQuery(String sql) 执行给定的 SQL 语句,它返回一个 ResultSet 对象。
executeUpdate(String sql) 执行给定的 SQL 语句,它可能会影响数据库中的任何数据。executeUpdate() 方法返回受影响的行数。
execute(String sql) 执行给定的 SQL 语句,该语句可能会返回多个结果。execute() 方法返回一个 boolean 值,指示第一个结果是否是 ResultSet 类型。
addBatch(String sql) 将给定的 SQL 语句添加到当前对象的批处理命令列表中。
clearBatch() 从此 Statement 对象的当前命令列表中删除所有命令。
executeBatch() 提交一批更新命令到数据库。executeBatch() 方法返回一个 int 数组,它表示批处理中每个命令影响的行数。
close() 释放此 Statement 对象使用的所有资源。

ResultSet

  • 执行查询后返回的对数据库的结果集表示。ResultSet是一个接口,它包含了一个表的所有行以及每个行的各个列的值
方法名 解释
next() 将结果集中的光标移到下一行。
getInt(int columnIndex) 和 getInt(String columnName) 获取指定列的 int 类型的值。
getDouble(int columnIndex) 和 getDouble(String columnName) 获取指定列的 double 类型的值。
getString(int columnIndex) 和 getString(String columnName) 获取指定列的 String 类型的值。
getDate(int columnIndex) 和 getDate(String columnName) 获取指定列的 java.sql.Date 类型的值。
getTime(int columnIndex) 和 getTime(String columnName) 获取指定列的 java.sql.Time 类型的值。
getTimestamp(int columnIndex) 和 getTimestamp(String columnName) 获取指定列的 java.sql.Timestamp 类型的值。
getObject(int columnIndex) 和 getObject(String columnName) 获取指定列的 java.lang.Object 类型的值。
wasNull() 如果上一次获取的值为空,返回 true。
close() 释放资源,关闭 ResultSet 对象。

PreparedStatement

  • 继承Statement接口,但能够提供高程序的性能和安全性,对SQL语句进行了预编译处理,并且可以通过参数化查询来防止SQL注入攻击。
方法名 解释
setString(int parameterIndex, String x) 给指定的参数设置 String 类型的值。
setInt(int parameterIndex, int x) 给指定的参数设置 int 类型的值。
setDouble(int parameterIndex, double x) 给指定的参数设置 double 类型的值。
setFloat(int parameterIndex, float x) 给指定的参数设置 float 类型的值。
setLong(int parameterIndex, long x) 给指定的参数设置 long 类型的值。
setDate( int parameterIndex, Date x ) 给指定的参数设置 java.sql.Date 类型的值。
setTime(int parameterIndex, Time x) 给指定的参数设置 java.sql.Time 类型的值。
setTimestamp(int parameterIndex, Timestamp x) 给指定的参数设置 java.sql.Timestamp 类型的值。
setObject(int parameterIndex, Object x) 给指定的参数设置 Object 类型的值。
setNull(int parameterIndex, int sqlType) 给指定的参数设置 null 值。
executeQuery() 执行带参数的查询并返回 ResultSet 对象。
executeUpdate() 执行带参数的更新语句。
addBatch() 添加一个批处理命令。
clearBatch() 清除所有之前添加的批处理命令。
executeBatch() 执行所有添加的批处理命令。
close() 释放资源,关闭 PreparedStatement 对象。

SQL注入

  • 常见的数据库漏洞,攻击者利用应用程序对输入数据的过滤和验证不严格,将恶意代码插入SQL语句中,获取到未授权的数据或者执行恶意操作。
  • SQL注入是一种比较隐蔽的攻击方式,因为它可以绕过应用程序的认证和访问控制,进而直接利用存在漏洞的SQL语句进行数据库操作。

数据源

  • 在实际开发,为了管理连接池和数据源,可以用一些第三方连接池框架,比如C3P0和Druid等
  • DataSource作为一个轻量级的数据库连接池,可以大大提高系统的性能,扩展和维护性。使用DataSource时,需要先配置驱动类名,URL,用户名,密码,初始化连接数量,最大连接数量,超时时间等。当应用程序需要连接数据库时候,可以从数据源中获取连接来执行相应操作。

DataSource的获取与释放

  • 通过JNDI获取DataSource对象时,通常需要进行初始化,创建一个InitialContext对象,将相关的参数信息放入Context中然后查找数据源。使用后,需要将连接释放会连接池。
    //初始化Context对象。
    Context ctx = new InitialConrext();、
    //根据JNDI名称查找DataSource对象。
    DataSource dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb");
    //从数据源中获取连接
    Connection conn = dataSource.getConnection();
    //使用连接进行数据操作
    // ..........
    //释放连接
    conn.close();

数据源的配置方式

  • DataSource 可以通过XML或Properties文件进行配置。对Spring框架等,也支持java代码的配置方式来获取数据源

线程安全性

  1. 为每个线程创建单独的Connection对象。可以使用ThreadLocal对象来保证每个线程都有自己的对象
  2. 连接池管理连接资源,能够对连接对象进行有效的监控和管理,从而避免了多个线程竞争同一个Connection对象的问题。允许线程取走,但是使用后归还连接池,供其他复用。
  3. 确保事务的独立性,每个线程会开启事物,提交或回滚事物,可以保证多个线程之间不会干扰彼此。

批处理

简介

  • 将多个命令按照顺序集成在一个文件中,批量执行的技术。通过一系列脚本或命令来完成。

Statement处理

  1. 使用Statement对象进行批处理,通过addBatch()将多个SQL命令添加到一个批处理中去,并使用executeBatch()方法来执行批处理。

Statement statement = connection.createStatement();
statement.addBatch("INSERT INTO user(name,age) values('Lily',18)");
statement.addBatch("INSERT INTO user(name,age) values('Tom',20)");
statement.addBatch("UPDATE user SET age='19' WHERE id='1'");
int[] count = statement.executeBatch(); //批量执行SQL语句
connection.commit();// 提交事务

PreparedStatement处理

同上

String INSERT_SQL = "INSERT INTO user(name,age) values(?,?)";
PreparedStatement pstmt = con.prepareStatement(INSERT_SQL);
pstmt.setString(1, "Lily");
pstmt.setInt(2, 18);
pstmt.addBatch();
pstmt.setString(1, "Tom");
pstmt.setInt(2, 20);
pstmt.addBatch();
int[] count = pstmt.executeBatch();
connection.commit();// 提交事务

Spring批处理实现大规模数据库操作

  1. 一般要创建Job,Step,ItemReader,ItemProcessor,ItemWriter

Job:批处理的最顶层组件,表示一个或多个并行 Step 的顺序运行。可以将其视为一个顶级容器,可包含多个 Step。

Step:是 Batch 处理的主要单位,表示一个任务步骤。可以对每一个步骤进行配置,比如设置读取文件、处理逻辑、验证等。

ItemReader:用于读取数据,通常从文件或数据库中读取数据。每次读取一条数据进行处理。

ItemProcessor:对 ItemReader 返回的数据进行进一步处理,可以对数据进行过滤、转换等操作,比如将一定格式的文本转化成 Java 对象。

ItemWriter:根据需要将读取到的数据写入到指定位置,如写入到数据库、写入到文件等。

  1. 配置Job和Step
    需要创建job和step的配置类,这些将负责配置Batch的核心组件,数据源,事务和监听器,通过XML文件或Java Config 进行配置,实现Batch批处理

    @Configuration
    @EnableBatchProcessing
    public class BatchConfiguration {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public Step step1() {
    return steps.get("step1")
    .<String, String>chunk(10)
    .reader(reader())
    .processor(processor())
    .writer(writer())
    .build();
    }

    @Bean
    public Job job(Step step1) throws Exception {
    return jobs.get("job")
    .incrementer(new RunIdIncrementer())
    .flow(step1)
    .end()
    .build();
    }

    //定义具体的 Reader、Processor、Writer
    }

  2. 定义 ItemProcessor、ItemReader 和 ItemWriter
    Batch 模块提供了大量优秀的处理器和读写器,这些对象可以快速地实现批处理任务。