JDBC基础知识复习
1、JDBC连接数据库
分3步:导入、注册、创建连接对象
1.1、导入JDBC驱动
导入对应数据库的驱动包(Jar文件),或者使用mvn导入对应数据库的依赖。
1.2、注册JDBC驱动程序
2个方法注册驱动,以Mysql为例子
Class.forName("com.mysql.jdbc.Driver")
,抛一个ClassNotFoundException
的异常DriverManager.registerDriver(new com.mysql.jdbc.Driver())
1.3、创建连接对象
一般使用DriverManager.getConnection(String url, String user, String pass)方法
获取
还有另外两种:
getConnection(String url)方法
getConnection(String url, Properties prop)方法
1.4、关闭JDBC连接
代码:Connection对象的close()方法
1.5、每种数据库对应的驱动名和URL
如下表:
JDBC驱动程序的名称 | URL | |
---|---|---|
Mysql | com.mysql.jdbc.Driver | jdbc:mysql://hostname:port/ databaseName |
Oracle | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@hostname:port Number:databaseName |
2、JDBC接口
通过使用 JDBC Statement, CallableStatement 和 PreparedStatement 接口定义的方法和属性,使可以使用 SQL 或 PL/SQL 命令和从数据库接收数据。
接口 | 应用场景 |
---|---|
Statement | 当在运行时使用静态 SQL 语句时(Statement接口不能接收参数) |
PreparedStatement | 当计划多次使用 SQL 语句时(PreparedStatement 接口接收在运行时输入参数) |
2.2、Statement
我们需要使用 Connection 对象的 createStatement() 方法
进行创建。
Statement的方法:
方法 | 说明 |
---|---|
boolean execute(String SQL) | 如果 ResultSet 对象可以被检索返回布尔值 true,否则返回 false。使用这个方法来执行 SQL DDL 语句,或当需要使用真正的动态 SQL |
int executeUpdate(String SQL) | 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句。返回值是一个整数,指示受影响的行数(即更新计数) |
ResultSet executeQuery(String SQL) | 返回 ResultSet 对象。用于产生单个结果集的语句,例如 SELECT 语句 |
释放Statement对象的方法是close()
2.3、PreparedStatement
占位符的概念而已,序号从1开始(不是从0开始哦)
2.4、两者区别
Statement适合静态SQL,PreparedStatement适合动态SQL。
因为PreparedStatement可以防止SQL注入!
3、ResultSet集合
结果集通常是通过执行查询数据库的语句生成,表示数据库查询结果的数据表。ResultSet 对象具有指向其当前数据行的光标。
ResultSet接口的方法可分为3类:
- 导航方法:用于移动光标
- 获取方法:用于查看当前行的光标所指向的列中的数据
- 更新方法:用于更新当前行的列中的数据
3.1、导航
迭代集合
3.2、获取
使用get方法
3.3、更新
使用update方法
4、事务
与数据库理论的事务概念一样,必须具有原子性、一致性、隔离性、持久性。
需要先关闭提交的代码:使用Connection的setAutoCommit(false)方法
4.1、事务提交
使用Connection对象的commit()方法
4.2、事务回滚
使用Conncetion对象的rollback()方法
5、实现自己的数据库连接池
使用之前项目的图像算法中的均值hash的数据表:
5.1、自己实现的连接池
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* 数据库连接池
* 循环链表实现
* @author zzw
*/
public class DBPool {
/**
* 池大小
*/
private static final int size = 20;
/**
* 数据库驱动名
*/
private static final String driverName = "com.mysql.jdbc.Driver";
/**
* 数据库名
*/
private static final String url = "jdbc:mysql://localhost:3306/imghashdb";
/**
* 数据库用户名
*/
private static final String user = "root";
/**
* 数据库密码
*/
private static final String password = "3306";
/**
* 连接池
*/
private static final LinkedList<Connection> pool = new LinkedList<>();
// 工具类不配实例化
private DBPool() {}
/**
* 创建size个连接对象放入连接池
*/
private static void createConnection() {
for(int i=0;i<size;i++) {
try {
pool.add(DriverManager.getConnection(url, user, password));
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 静态代码块用于加载数据库驱动
static {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取一个数据库连接
* @return Connection
*/
public static synchronized Connection getConn() {
if(pool.isEmpty()) {
createConnection();
}
return pool.removeFirst();
}
/**
* 归还一个数据库连接
* @param conn 数据库连接
*/
public static synchronized void callback(Connection conn) {
// 如果当前连接池大小超过规定连接池大小,则不再归还
if(pool.size() > size) {
try {
conn.close();
System.out.println("此连接不必归还");
} catch (SQLException e) {
e.printStackTrace();
}
}else {
pool.add(conn);
}
}
}
5.2、测试
测试代码如下:
package app;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import util.DBPool;
public class App {
public static void main(String[] args) throws SQLException {
// 1. 增
Connection conn = DBPool.getConn();
conn.setAutoCommit(false);
PreparedStatement prepareStatement = conn.prepareStatement("insert ahash values(?, ?, ?)");
prepareStatement.setInt(1, 1);
prepareStatement.setString(2, "00101101");
prepareStatement.setString(3, "hello.jpg");
int insert = prepareStatement.executeUpdate();
System.out.println(insert);
conn.commit();
DBPool.callback(conn);
// 2. 改
//# 类似..略
// 3. 查
conn = DBPool.getConn();
prepareStatement = conn.prepareStatement("select * from ahash");
ResultSet resultSet = prepareStatement.executeQuery();
resultSet.first();
while(resultSet.next()) {
System.out.println("id: "+resultSet.getInt(1)+", hash: "+resultSet.getString(2).substring(0, 8)+"..., path: "+resultSet.getString(3));
}
DBPool.callback(conn);
// 4. 删
//# 类似..略
}
}
5.3、测试结果
控制台输出: