摘要
本文主要介紹了JDBC的基本使用方法,並提供了完整的代碼實現。首先介紹了JDBC的背景,然後給出了JDBC的基本操作代碼實現,在其中加入詳細的註解,解釋其各步驟的目的與用意。最後解釋了Druid連接池,以及相關的JDBC面試問題。
一、JDBC介紹
Java類型與數據庫類型不一致而產生了衝突,所以需要一種連接器將兩種數據類型進行轉換,從而實現Java訪問數據庫的功能。數據庫產品較多,若各個廠家實現連接器的架構不一致,從而導致開發者需要對代碼進行重構,也導致了數據庫與項目的強耦合性。
Sun公司爲了簡化、統一對數據庫的操作,定義了一套java操作數據庫的接口的規範,稱之爲JDBC(Java Database Connectivity)。各數據庫產品公司,只需根據JDBC接口進行相關實現,開發者根據接口進行編程,從而降低了耦合性,只需要引入數據庫對應的JDBC jar包即可。
二、JDBC的使用
package ft.test.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
class App {
@Test
void test() {
Connection conn = null;
PreparedStatement preparedStatement = null;
try {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC";
String userName = "root";
String password = "123456789";
Class clz = Class.forName(driver);
conn = DriverManager.getConnection(url, userName, password);
//要獲得數據庫table的每列字段信息,需要創建元數據對象DatabaseMetaData
DatabaseMetaData metaData = conn.getMetaData();
//獲取名爲students的table各列信息
ResultSet columnSet = metaData.getColumns(null, url, "students", "%");
//循環獲取table的各列
while(columnSet.next()) {
//獲取該列字段的類型信息
String type = columnSet.getString("TYPE_NAME");
System.out.printf("columnType = %s ",type);
//獲取該列字段的名稱
String name = columnSet.getString("COLUMN_NAME");
System.out.println("columnName = "+name);
}
System.out.println("###########################################");
String sql = "select * from students where age = ?";
//創建PreparedStatement對象
preparedStatement = conn.prepareStatement(sql);
//向sql語句中填充值
preparedStatement.setObject(1, 100);
//對數據庫執行操作
ResultSet results = preparedStatement.executeQuery();
//循環遍歷結果集中的每一列
while(results.next()) {
for(int i=0; i<results.getMetaData().getColumnCount(); i++) {
//獲取每列字段的值
System.out.print(results.getObject(i+1)+" ");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
//執行相應的關閉操作
try {
if(conn != null) {
conn.close();
}
if(preparedStatement != null) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
程序執行結構如下所示:
columnType = INT columnName = id
columnType = VARCHAR columnName = name
columnType = INT columnName = age
columnType = VARCHAR columnName = password
###########################################
1 feng 100 feng
三、連接池
3.1、連接池介紹
Java訪問數據庫時,一次數據庫訪問對應一個物理連接,每次訪問數據庫都需要爲其打開物理連接,結束時爲其關閉物理連接,在百萬訪問量時,這種數據庫訪問方式造成了巨大的系統開銷,需要改進。
基於以上缺點,連接池提出了改進方式。系統運行時,提前創建足夠的物理連接,這些物理連接稱爲連接池。當Java需要一個物理連接時,不需要創建新的物理連接而是從連接池中直接取,用完時不需要關閉物理連接,而是將其歸還於連接池中。這樣的策略大大降低了系統的開銷。
3.2、Druid連接池的使用
Druid是阿里巴巴開發的號稱爲監控而生的數據庫連接池,Druid是目前最好的數據庫連接池。在功能、性能、擴展性方面,都超過其他數據庫連接池,同時加入了日誌監控,可以很好的監控DB池連接和SQL的執行情況。需要下載Druid jar包並加入build path。
使用連接池的具體代碼如下所示:
package ft.test.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;
import com.alibaba.druid.pool.DruidDataSource;
class App {
@Test
void test() {
Connection conn = null;
PreparedStatement preparedStatement = null;
try {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC";
String userName = "root";
String password = "123456789";
//使用連接Druid連接池
DruidDataSource druid=new DruidDataSource();
druid.setDriverClassName(driver);
druid.setUrl(url);
druid.setUsername(userName);
druid.setPassword(password);
conn = druid.getConnection();
//要獲得數據庫table的每列字段信息,需要創建元數據對象DatabaseMetaData
DatabaseMetaData metaData = conn.getMetaData();
//獲取名爲students的table各列信息
ResultSet columnSet = metaData.getColumns(null, url, "students", "%");
//循環獲取table的各列
while(columnSet.next()) {
//獲取該列字段的類型信息
String type = columnSet.getString("TYPE_NAME");
System.out.printf("columnType = %s ",type);
//獲取該列字段的名稱
String name = columnSet.getString("COLUMN_NAME");
System.out.println("columnName = "+name);
}
System.out.println("###########################################");
String sql = "select * from students where age = ?";
//創建PreparedStatement對象
preparedStatement = conn.prepareStatement(sql);
//向sql語句中填充值
preparedStatement.setObject(1, 100);
//對數據庫執行操作
ResultSet results = preparedStatement.executeQuery();
//循環遍歷結果集中的每一列
while(results.next()) {
for(int i=0; i<results.getMetaData().getColumnCount(); i++) {
//獲取每列字段的值
System.out.print(results.getObject(i+1)+" ");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
//執行相應的關閉操作
try {
if(conn != null) {
conn.close();
}
if(preparedStatement != null) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}