JDBC
由來與描述
- 沒有JDBC前
開發者想運算元據庫,必須需要了解每個資料庫對應的資料庫驅動程式API,由於每個資料庫驅動程式的API都不同,所以當需要遷移資料庫時,根本不平滑,需要大量修改與重寫
- 有了JDBC後
Sum公司也知道問題之後,就提出一種約束 —— JDBC規範,讓所有資料庫廠商都按照這個JDBC規範來開發資料庫驅動程式,以便於Java程式能用統一方式操作不同的資料庫,資料庫遷移變成可行
- JDBC描述
JDBC是一種Java web的規範,需要具體開發者(資料庫廠商)來實現
JDBC
常用四大API
- DriverManager
作用:
1、註冊驅動
Class.forName("com.jdbc.mysql.Driver");
2、獲取連線
Connection conn = DriverManager.getConnection();
- Connection
作用:
1、建立執行SQL語句的物件(3種)
Statement createStatement() // 執行SQL語句
PreparedStatement prepareStatement() // 預編譯SQL並執行
CallableStatement prepareCall() // 執行SQL儲存過程
2、進行事務管理
setAutoCommit(boolean b)
commit()
rollback()
- Statement
作用:
1、執行SQL語句
boolean execute(String sql) // 執行SQL語句,執行select就返回true,否則返回false
ResultSet executeQuery(String sql) // 執行SQL中的select語句
int executeUpdate(String sql) // 執行SQL中的insert/update/delete語句
2、執行批量SQL語句
addBatch(String sql) // 新增到批量處理
executeBatch() // 執行批量處理
clearBatch() // 清空批量處理
- ResultSet
(select語句)查詢結果的集合
作用:獲取到查詢的結果
next() //判斷是否有下一條資料
getXXX() //根據資料型別獲取查詢記錄的資料
getObject() //通用獲取資料方法
JDBC資源釋放
釋放原則:
晚建立,早釋放
;資源稀有,不釋放很快會阻塞
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from user");
rs.close();
stmt.close();
conn.close();
JDBC CURD操作
- 增加
Connection conn = null;
Statement stmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 獲取執行SQL語句物件
stmt = conn.createStatement();
// 編寫SQL
String sql = "insert into user values ("xiaomin","女人",12)";
// 執行SQL語句
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("插入成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 更新
Connection conn = null;
Statement stmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 獲取執行SQL語句物件
stmt = conn.createStatement();
// 編寫SQL
String sql = "update user set name = `wt`";
// 執行SQL語句
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("更新成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 刪除
Connection conn = null;
Statement stmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 獲取執行SQL語句物件
stmt = conn.createStatement();
// 編寫SQL
String sql = "delete from user where id = 3";
// 執行SQL語句
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("刪除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 查詢
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 獲取執行SQL語句物件
stmt = conn.createStatement();
// 編寫SQL
String sql = "select * from user";
// 執行SQL語句
rs = stmt.executeQuery(sql);
if(rs.next()){
System.out.print(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs != null){
try{
rs .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
rs = null;
}
}
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
JDBC SQL隱碼攻擊解決方案
開發時,使用
PreparedStatement物件
取代Statement物件
來執行SQL,有效避免SQL隱碼攻擊
- 增加
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 編寫SQL
String sql = "insert into user values (?,?,?)";
// 獲取執行SQL語句物件
pstmt = conn.preparedStatement(sql);
// 設定引數
pstmt.setString(1, "qqq");
pstmt.setString(2, "bbb");
pstmt.setString(3, "ccc");
// 執行SQL語句
int i = pstmt.executeUpdate();
if(i > 0){
System.out.println("插入成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
pstmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 更新
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 編寫SQL
String sql = "update user set name = ?, age = ?, pwd = ? where id = ?";
// 獲取執行SQL語句物件
pstmt = conn.preparedStatement(sql);
// 設定引數
pstmt.setString(1, "wt");
pstmt.setString(2, 15);
pstmt.setString(3, "basdcx");
pstmt.setString(4, 10);
// 執行SQL語句
int i = pstmt.executeUpdate();
if(i > 0){
System.out.println("更新成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
pstmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 刪除
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 編寫SQL
String sql = "delete from user where id = ?";
// 獲取執行SQL語句物件
pstmt = conn.preparedStatement(sql);
// 設定引數
pstmt.setString(1, 16);
// 執行SQL語句
int i = pstmt.executeUpdate();
if(i > 0){
System.out.println("刪除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
pstmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 查詢
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 獲得連線
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 編寫SQL
String sql = "select * from user where sex = ?";
// 獲取執行SQL語句物件
pstmt = conn.preparedStatement(sql);
// 設定引數
pstmt.setString(1, `男`);
// 執行SQL語句
rs = pstmt.executeQuery();
while(rs.next()){
System.out.println(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs != null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
rs = null;
}
}
if(pstmt != null){
try{
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
pstmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
連線池(資料來源)JDBC優化技術
資料庫連線頻繁建立與消耗,在資源使用上是一種浪費
- 常用連線池
C3P0、HikariCP、Druid、Tomcat、Dbcp
- 用法(以C3P0為例)
ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 只需一個物件
// 獲取連線
Connection conn = dataSource.getConnection();