1. JDBC简介
使用JDBC的好处是:
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发;
- Java程序编译期仅依赖java.sql包,不依赖具体数据库的jar包;
- 可随时替换底层数据库,访问数据库的Java代码基本不变。
2. JDBC查询
连接
核心代码是DriverManager
提供的静态方法getConnection()
。因为JDBC连接是一种昂贵的资源,所以使用后要及时释放。使用try (resource)
来自动释放JDBC连接是一个好方法
try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) {
...
}
查询
第一步,通过Connection
提供的createStatement()
方法创建一个Statement
对象,用于执行一个查询;
第二步,执行Statement
对象提供的executeQuery("SELECT * FROM students")
并传入SQL语句,执行查询并获得返回的结果集,使用ResultSet
来引用这个结果集;
第三步,反复调用ResultSet
的next()
方法并读取每一行结果。
try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) {
try (Statement stmt = conn.createStatement()) {
try (ResultSet rs = stmt.executeQuery("SELECT id, grade, name, gender FROM students WHERE gender=1")) {
while (rs.next()) {
long id = rs.getLong(1); // 注意:索引从1开始
long grade = rs.getLong(2);
String name = rs.getString(3);
int gender = rs.getInt(4);
}
}
}
}
注意要点:
Statment
和ResultSet
都是需要关闭的资源,因此嵌套使用try (resource)
确保及时关闭;
rs.next()
用于判断是否有下一行记录,如果有,将自动把当前行移动到下一行(一开始获得ResultSet
时当前行不是第一行);
ResultSet
获取列时,索引从1
开始而不是0
;
必须根据SELECT
的列的对应位置来调用getLong(1)
,getString(2)
这些方法,否则对应位置的数据类型不对,将报错。
SQL注入
使用PreparedStatement
可以完全避免SQL注入的问题,因为PreparedStatement
始终使用?
作为占位符,并且把数据连同SQL本身传给数据库,这样可以保证每次传给数据库的SQL语句是相同的,只是占位符的数据不同,还能高效利用数据库本身对查询的缓存。
数据类型
SQL数据类型 | Java数据类型 |
---|---|
BIT, BOOL | boolean |
INTEGER | int |
BIGINT | long |
REAL | float |
FLOAT, DOUBLE | double |
CHAR, VARCHAR | String |
DECIMAL | BigDecimal |
DATE | java.sql.Date, LocalDate |
TIME | java.sql.Time, LocalTime |
注意:只有最新的JDBC驱动才支持LocalDate
和LocalTime
。
3. JDBC更新
插入、更新、删除
使用JDBC执行INSERT
、UPDATE
和DELETE
都可视为更新操作;
更新操作使用PreparedStatement
的executeUpdate()
进行,返回受影响的行数。
4. JDBC事务
事务的四个特性(ACID):
- Atomicity:原子性
- Consistency:一致性
- Isolation:隔离性
- Durability:持久性
JDBC提供了事务的支持,使用Connection可以开启、提交或回滚事务。
Connection conn = openConnection();
try {
// 关闭自动提交:
conn.setAutoCommit(false);
// 执行多条SQL语句:
insert(); update(); delete();
// 提交事务:
conn.commit();
} catch (SQLException e) {
// 回滚事务:
conn.rollback();
} finally {
conn.setAutoCommit(true);
conn.close();
}
5. JDBC Batch
在JDBC代码中,我们可以利用SQL数据库的这一特性,把同一个SQL但参数不同的若干次操作合并为一个batch执行。
使用JDBC的batch操作会大大提高执行效率,对内容相同,参数不同的SQL,要优先考虑batch操作。
6. JDBC连接池
数据库连接池是一种复用Connection
的组件,它可以避免反复创建新连接,提高JDBC代码的运行效率;
可以配置连接池的详细参数并监控连接池。