一、JDBC Java Database Connectivity
1. 概念
Java Database Connectivity
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
官方文档地址:
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-usagenotes-basic.html
简而言之,通过jdbc,我们的Java程序可以真正得访问关系型数据库。
比如:
package com.wang.jdbc;
import com.wang.pojo.Category;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
public class JDBCTest {
/**
* 在这里 通过JDBC技术 完成对数据库的查询
* 并且把查询到的数据在 java代码控制台显示:
* 最最要做的第一件事情就是 把驱动导进来
*/
public static void main(String[] args) throws Exception{
//按照套路 完成就行 套路是六步
// 1:注册驱动 把mysql实现的驱动类加载到内存中
// DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2: 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydb03";
String username = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, username, password);
//3:获取语句执行对象(平台)
Statement state = connection.createStatement();
//4:执行sql语句
String sql = "select * from category";
//在语句执行平台(Statement)执行自定义的sql语句
ResultSet resultSet = state.executeQuery(sql);
//state.
ArrayList
//5:处理结果集
while(resultSet.next()){//结果集中 下一条是否有记录
// 解析当前行记录
int cid = resultSet.getInt("cid");
String cname = resultSet.getString("cname");
Category category = new Category();
category.setCid(cid);
category.setCname(cname);
list.add(category);
}
System.out.println(list);
// 6:释放资源
// 从后往前不会少 从小往大不会错
resultSet.close();
state.close();
connection.close();
}
}
2. JDBC 原生六步
2.1 注册驱动
把mysql实现的驱动类加载到内存中。
不同的数据库,实现的驱动类不同,即使都是mysql数据库, 驱动类也是不同的。
MySQL驱动类:
5版本: com.mysql.jdbc.Driver
6及6以上版本: com.mysql.cj.jdbc.Driver
Oracle驱动类:
oracle.jdbc.driver.OracleDriver
在程序中注册驱动
Class.forName("com.mysql.jdbc.Driver");
2.2 获取连接对象
需要提供访问数据库的url、username、password
String url = "jdbc:mysql://localhost:3306/mydb03";
String username = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, username, password);
2.3 获取语句执行对象(平台)
通过connection对象来获取能够执行我们的sql语句的平台
Statement state = connection.createStatement();
2.4 执行sql语句
这里有两个方法可以执行sql语句,
SELECT
ResultSet executeQuery(String sql) throws SQLException;
INSERT UPDATE DELETE
int executeUpdate(String sql) throws SQLException;
INSERT方法实际代码:
String sql = "insert into category values(10,'demo04')";
int row = state.executeUpdate(sql);
SELECT方法的实际代码:
//4:执行sql语句
String sql = "select * from category";
//在语句执行平台(Statement)执行自定义的sql语句
ResultSet resultSet = state.executeQuery(sql);
源码中对于这两个方法的解释,嫌长的话可以跳过
/**
* Executes the given SQL statement, which returns a single
* ResultSet
object.
*
* Note:This method cannot be called on a
* PreparedStatement
or CallableStatement
.
* @param sql an SQL statement to be sent to the database, typically a
* static SQL SELECT
statement
* @return a ResultSet
object that contains the data produced
* by the given query; never null
* @exception SQLException if a database access error occurs,
* this method is called on a closed Statement
, the given
* SQL statement produces anything other than a single
* ResultSet
object, the method is called on a
* PreparedStatement
or CallableStatement
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
ResultSet executeQuery(String sql) throws SQLException;
/**
* Executes the given SQL statement, which may be an INSERT
,
* UPDATE
, or DELETE
statement or an
* SQL statement that returns nothing, such as an SQL DDL statement.
*
* Note:This method cannot be called on a
* PreparedStatement
or CallableStatement
.
* @param sql an SQL Data Manipulation Language (DML) statement, such as INSERT
, UPDATE
or
* DELETE
; or an SQL statement that returns nothing,
* such as a DDL statement.
*
* @return either (1) the row count for SQL Data Manipulation Language (DML) statements
* or (2) 0 for SQL statements that return nothing
*
* @exception SQLException if a database access error occurs,
* this method is called on a closed Statement
, the given
* SQL statement produces a ResultSet
object, the method is called on a
* PreparedStatement
or CallableStatement
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
int executeUpdate(String sql) throws SQLException;
2.5 处理结果集
根据不同的业务需求来获取不同的结果集
//5:处理结果集
//update create delete:
System.out.println("影响:"+row+"行");
//select:
while (resultSet.next()) {
// 移到查询的数据上 解析数据
int cid = resultSet.getInt("cid");
String cname = resultSet.getString("cname");
System.out.println("cid:"+cid+"cname:"+cname);
}
2.6 释放资源
把结果集对象resultSet、执行sql语句平台statement、数据库连接对象connection的资源通过close方法释放掉。
//6. 释放资源
//从进到远释放结果集、执行SQL语句平台、获取语句对象
resultSet.close();
state.close();
conn.close();
3. JDBC 的工具类的封装
从原生六步里可以看到如果每次连接数据库都要写一遍数据库地址、name、password,怕不是要累死,那么我们可不可以把相同的步骤封装到一个工具类中,直接调用这个工具类的方法就可以调用了所有需要的connection对象、statement对象和结果集。
那么聪明的人类就想到了使用工具类和配置文件来将重复繁琐的任务封装,需要连接的时候调用工具类的一个方法就可以连接数据库。
而关于数据库的配置信息(url、password、username)放到配置文件中就可以了。这样大家就可以各司其职,而不是都搅在一起维护也麻烦调用也麻烦。
3.1 配置文件 db. properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb03
jdbc.username=root
jdbc.password=root
配置文件放到resources文件夹下或者直接挂载在src下
3.2 工具类 JdbcUtils
注意,如果配置文件放在src的子文件resources下,就需要写明src下的路径。如果直接放在src下就直接写properties配置文件的文件名db就可以了。
ResourceBundle bundle = ResourceBundle.getBundle("resources/db");
package com.wang.utils;
import java.sql.*;
import java.util.ResourceBundle;
/*
JDBC 工具类
用来封装 我们JDBC六步常用的内容
1:获取连接对象
2:释放资源
*/
public class JdbcUtils {
static Connection connection = null;
static {
try {
System.out.println("解析配置文件");
//解析配置文件db.properties
ResourceBundle bundle = ResourceBundle.getBundle("resources/db");
//解析配置文件各个参数
String driver = bundle.getString("jdbc.driver");
String url = bundle.getString("jdbc.url");
String username = bundle.getString("jdbc.username");
String password = bundle.getString("jdbc.password");
//注册驱动
Class.forName(driver);
//获取连接对象
connection = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}
}
// 获取连接对象
public static Connection getConnection(){
//想要连接对象 必须先解析配置文件 配置文件解析几次?
return connection;
}
//释放资源
public static void close(ResultSet rs, Statement state,Connection conn) throws Exception{
if(rs!=null){
rs.close();
}
if(state!=null){
state.close();
}
if(conn!=null){
conn.close();
}
}
}
3.3 封装后的JDBC原生六步写法
INSERT Update delete
public class InsertIntoDemo {
public static void main(String[] args) throws Exception{
Connection conn = JdbcUtils.getConnection();
//3:获取语句执行对象
Statement state = conn.createStatement();
// 4:执行sql语句
String sql = "insert into category values(10,'demo04')";
int row = state.executeUpdate(sql);
// 5:处理结果集
System.out.println("影响:"+row+"行");
//6:释放资源
JdbcUtils.close(null,state,conn);
}
}
SELECT
public class InsertIntoDemo {
public static void main(String[] args) throws Exception{
Connection conn = JdbcUtils.getConnection();
//3:获取语句执行对象
Statement state = conn.createStatement();
// 4:执行sql语句
String sql = "select * from category";
ResultSet resultSet = state.executeQuery(sql);
// 5:处理结果集
while (resultSet.next()) {
int cid = resultSet.getInt("cid");
String cidStr = String.valueOf(cid);
String cname = resultSet.getString("cname");
System.out.println(cidStr+" : "+cname);
}
//6:释放资源
JdbcUtils.close(null,state,conn);
}
}