JDBC 学习笔记

JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。

执行流程:

  • 连接数据源,如:数据库。
  • 为数据库传递查询和更新指令。
  • 处理数据库响应并返回的结果。

JDBC 快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//注册JDBC驱动
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "root";
//创建数据库链接
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into person (id,name,sex,age) value(1,'xiaoming',1,18)";
//获取SQL执行对象
Statement statement = connection.createStatement();
//执行SQL
int i = statement.executeUpdate(sql);
System.out.println(i);
//释放资源
statement.close();
connection.close();

在 MySQL5 后注册 JDBC 驱动可以省略

DriverManager

DriverManagerd 的作用:

  1. 注册驱动
  2. 获取数据库连接

jdbc:mysql://localhost:3306/mydb 中,如果连接的数据库是本地数据库,端口为 3306 时,可以缩写为 jdbc:mysql:///mydb

Connection

Connection (数据库连接对象) 作用:

  1. 获取执行 SQL 的对象
  2. 管理事务

获取执行 SQL 的对象

方法注释
createStatement获取普通执行 SQL 对象
prepareStatement获取预编译 SQL 的 SQL 执行对象,防止 SQL 注入
prepareCall获取存储过程对象

管理事务

Mysql 事务管理过程

  1. 开启事务 BEGIN/START TRANSACTION
  2. 提交事务 COMMIT
  3. 回滚事务 ROLLBACK

JDBC 事务管理

  1. 开启事务 setAutoCommit (boolean autoCommint)
  2. 提交事务 commit ()
  3. 回滚事务 rollback ()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String url = "jdbc:mysql:///mydb";
String username = "root";
String password = "root";
//创建数据库链接
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into person (id,name,sex,age) value(1,'小红',0,18)";
String sql2 = "insert into person (id,name,sex,age) value(1,'小名',1,18)";
Statement statement = connection.createStatement();
try {
connection.setAutoCommit(false);
System.out.println(statement.executeUpdate(sql));
System.out.println(statement.executeUpdate(sql2));
connection.commit();
}catch (Exception e){
connection.rollback();
e.printStackTrace();
}finally {
statement.close();
connection.close();
}

在代码中,插入的两个数据 ID 都为 1,因为在数据库中对 ID 做了唯一设置,所以当第二个数据插入时,会产生异常,但为了确保事务的正常,所以在同一个事务中的第一个 SQL 语句也应该回滚,所以在这个事务中,第一个 SQL 并没有能够提交,而是随着事务做了回滚操作。

Statement

Statement 的作用就是执行 SQL

方法返回值作用
executeUpdateint执行 DML、DDL 语句,返回 DML 影响的行数,DDL 语句执行成功也可能返回 0
executeQueryResultSet执行 DQL 语句,返回 ResultSet 对象

ResultSet

ResultSet 是结果集对象,封装了 DQL 语句的查询结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String url = "jdbc:mysql:///mydb";
String username = "root";
String password = "root";
//创建数据库链接
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "select * from person";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int sex = resultSet.getInt("sex");
int age = resultSet.getInt("age");
System.out.println(id+"\t"+name+"\t"+sex+"\t"+age);
}

小测试,将查询结果封装到对象,并且添加到集合中

创建 Person 实体类

1
代码过于简单重复已忽略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String url = "jdbc:mysql:///mydb";
String username = "root";
String password = "root";
//创建数据库链接
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "select * from person";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
ArrayList<Person> people = new ArrayList<>();
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int sex = resultSet.getInt("sex");
int age = resultSet.getInt("age");
Person person = new Person(id,name,sex,age);
people.add(person);
}

在原有代码的基础上进行修改,将查询到的结果封装到 Person 对象中,并且添加到 ArrayList 中

prepareStatement

预编译 SQL 语句,可以防止 SQL 注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String url = "jdbc:mysql:///mydb";
String username = "root";
String password = "root";
//创建数据库链接
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "select id from user where username = ? and password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"小明");
preparedStatement.setString(2,"123456");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println("登陆成功");
}
resultSet.close();
preparedStatement.close();
connection.close();

在 SQL 的参数设置时会对参数进行转义,并不会看出 SQL 语句的一部分

数据库连接池

  • 数据库连接池是个容器,负责分配、管理数据库连接
  • 它允许应用程序重复使用一个现有的数据库连接池,而不是重新建立一个
  • 释放空间时间超过最大空袭时间的数据库连接来避免没有释放数据库连接池而因其的数据库连接遗漏
  • 好吃
    • 资源重用
    • 提升系统响应时间
    • 避免数据库连接遗漏
1
2
3
4
5
Properties properties = new Properties();
properties.load(new FileInputStream("./Base/src/durid.properties"));
DataSource source = DruidDataSourceFactory.createDataSource(properties);
Connection connection = source.getConnection();
System.out.println(connection);
1
2
3
4
5
6
7
8
9
url=jdbc:mysql:///mydb
username=root
password=root
# 初始化连接池数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000