JDBC
Java DataBase Connectivity java數(shù)據(jù)庫連接
是一種數(shù)據(jù)庫訪問規(guī)則規(guī)范。
簡單使用
基本步驟:
- 注冊driver
- 建立連接
- 創(chuàng)建statement對象進(jìn)行交互
- 執(zhí)行sql 獲取結(jié)果
- 釋放資源
代碼舉例:
package com;
import java.sql.*;
public class Main {
public static void main(String[] args) {
Driver driver;
Connection connection;
Statement statement;
ResultSet res;
try {
driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
statement = connection.createStatement();
String sql = "select * from product";
res = statement.executeQuery(sql);
while(res.next()) {
System.out.println("pname: " + res.getString("pname")
+ "price: " + res.getDouble("price"));
}
res.close();
statement.close();
connection.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
maven依賴添加地址:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
釋放資源代碼整理
將釋放資源的邏輯可以提出來,寫出一個(gè)工具類
package com;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCUtils {
public static void close(ResultSet res, Statement statement, Connection connection) {
closeRes(res);
closeStatement(statement);
closeConnection(connection);
}
public static void closeRes(ResultSet res) {
try {
if(res != null) {
res.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
res = null;
}
}
public static void closeStatement(Statement statement) {
try {
if(statement != null) {
statement.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
statement = null;
}
}
public static void closeConnection(Connection connection) {
try {
if(connection != null) {
connection.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
connection = null;
}
}
}
優(yōu)化之后,上面的例子就可以寫成這樣:
package com;
import java.sql.*;
public class Main {
public static void main(String[] args) {
Driver driver;
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try {
driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver);
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
statement = connection.createStatement();
String sql = "select * from product";
res = statement.executeQuery(sql);
while(res.next()) {
System.out.println("pname: " + res.getString("pname")
+ "price: " + res.getDouble("price"));
}
}catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(res, statement, connection);// 在finally里去close()
}
}
}
關(guān)于注冊driver的優(yōu)化
看下源碼可以發(fā)現(xiàn)其內(nèi)部有個(gè)static代碼塊:
static {
try {
DriverManager.registerDriver(new Driver()); // 已經(jīng)注冊了一個(gè)Driver
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
內(nèi)部已經(jīng)進(jìn)行了driver的注冊,所以沒必要重復(fù)注冊第二個(gè)driver,按照文檔中的示例,可以采用Class.forName("com.mysql.jdbc.Driver").newInstance()(其實(shí)沒必要去newInstance()已經(jīng)有driver,這個(gè)操作浪費(fèi)空間);
優(yōu)化過后的代碼如下所示:
package com;
import java.sql.*;
public class Main {
public static void main(String[] args) {
Driver driver;
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try {
// driver = new com.mysql.cj.jdbc.Driver(); // 改用動(dòng)態(tài)加載一個(gè)driver類
Class.forName("com.mysql.cj.jdbc.Driver");
// DriverManager.registerDriver(driver); // com.mysql.cj.jdbc.Driver內(nèi)部已經(jīng)注冊過driver了 沒必要重復(fù)注冊
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
statement = connection.createStatement();
String sql = "select * from product";
res = statement.executeQuery(sql);
while(res.next()) {
System.out.println("pname: " + res.getString("pname")
+ "price: " + res.getDouble("price"));
}
}catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(res, statement, connection);
}
}
}
關(guān)于Class.forName(className), 在一些應(yīng)用中,無法事先知道使用者將加載什么類(比如本例中使用jdbc可能是其他數(shù)據(jù)庫),而必須讓使用者指定類名稱以加載類,可以使用 Class 的靜態(tài) forName() 方法實(shí)現(xiàn)動(dòng)態(tài)加載類。詳見Class.forName
jdbc.properties
上述例子中的數(shù)據(jù)庫配置等信息都是寫在代碼中的,我們一般是要從配置文件中讀取的,所以我們創(chuàng)建一個(gè)名為jdbc.properties的文件,如下:
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false
userName=root
password=Admin@123
然后我們修改JDBCUtils里面的代碼:
package com;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
static String driverClass = null; // 數(shù)據(jù)庫類型
static String url = null; // 數(shù)據(jù)庫地址
static String userName = null;
static String password = null;
static { // 默認(rèn)static代碼塊 讀取properties配置
try {
Properties properties = new Properties(); // 獲取Properties對象
InputStream setting = new FileInputStream("src/jdbc.properties"); // 獲取文件流
properties.load(setting);// properties對象加載讀取到的配置
driverClass = properties.getProperty("driverClass"); // 從配置中讀取特定的配置
url = properties.getProperty("url");
userName = properties.getProperty("userName");
password = properties.getProperty("password");
}catch (Exception e) {
e.printStackTrace();
}
}
// 注冊驅(qū)動(dòng)并且并且獲取連接Connection
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName(driverClass);
connection = DriverManager.getConnection(url, userName, password);
}catch (Exception e) {
e.printStackTrace();
}finally {
return connection;
}
}
// 釋放資源
public static void close(ResultSet res, Statement statement, Connection connection) {
closeRes(res);
closeStatement(statement);
closeConnection(connection);
}
public static void closeRes(ResultSet res) {
try {
if(res != null) {
res.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
res = null;
}
}
public static void closeStatement(Statement statement) {
try {
if(statement != null) {
statement.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
statement = null;
}
}
public static void closeConnection(Connection connection) {
try {
if(connection != null) {
connection.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
connection = null;
}
}
}
JDBC對數(shù)據(jù)庫的CRUD
- insert
@Test
public void testInsert() {
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try{
connection = JDBCUtils.getConnection();
statement = connection.createStatement();
String sql = "insert into product values(null, '泡椒鳳爪', 3, null, 5);";
int result = statement.executeUpdate(sql); // 執(zhí)行insert update delete的時(shí)候使用executeUpdate return int
if(result > 0) { // result為影響的行數(shù)
System.out.println("insert successfully!");
}else {
System.out.println("insert failed");
}
}catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(res, statement, connection);
}
}
update和delete同理
使用junit進(jìn)行單元測試
- 添加junit依賴
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
- 添加一個(gè)類,定義測試方法,給其加上@Test注解
import com.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestDemo {
@Test
public void testQuery() {
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try{
connection = JDBCUtils.getConnection();
statement = connection.createStatement();
String sql = "select * from product;";
res = statement.executeQuery(sql);
}catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(res, statement, connection);
}
}
}