Table of Contents
3:PreparedStatement與Statement的區別
4:代碼分析在上述對數據庫進行增刪改查的過程中,可以發現其共性部分,即通用的流程:
1:概述
本文借postgreSQL通過JDBC連接數據庫的示例,介紹了常見數據庫操作及JDBC的API、JDBC的一般工作流程及JDBC事務。
pgJDBC驅動可以使Java程序以標準的數據庫無關的java代碼連接pg。除了一些pg特定的是純java實現,因此只需要下載jar包就可以開幹了。
擴展PostgreSQL的外,該驅動程序提供了相當完整的JDBC3規範的實施。目標是完全符兼容,但現在還沒有兼容在todo list中列出
2:準備工作
A、下載安裝好postgreSQL數據庫。
B、新建一個java項目,並導入postgreSQL的JDBC驅動程序jar包(http://jdbc.postgresql.org/)。
3:Java連接postgreSQL代碼示例。
package weavernoth.wkl.action;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* Description:PostgreSQL的jdbc
* Date: 2020/4/28 - 上午 11:18
* author:
* version: V1.0
*/
public class JdbcCronJob {
@Override
public void execute() {
String url = "jdbc:postgresql://locahost:5432/test_db";
String usr = "root";
String psd = "123456";
Connection conn = null;
try {
Class.forName("org.postgresql.Driver");
conn = DriverManager.getConnection(url, usr, psd);
Statement st = conn.createStatement();
//Statement:適合只執行一次或極少執行的sql文。
//PreparedStatement:適合執行需要傳參並且會多次執行的sql文,並且一定程度上防止了sql注入。
//CallableStatement:適合執行存儲過程。
ResultSet rs = st.executeQuery("select id,name from tablename");
while (rs.next()) {
System.ouy.print(rs.getString(1));
System.ouy.print(rs.getString(2));
}
rs.close();
st.close();
conn.close();
} catch (Exception e) {
System.ouy.print(e);
e.printStackTrace();
}
}
}
3:PreparedStatement與Statement的區別
1:JDBC中執行sql對錶的查詢有三種方式,靜態SQL語句(Statement),動態SQL語句(PreparedStatement),與存儲過程(CallableStatement)三種方式,
2:java.sql包中的PreparedStatement 接口繼承了Statement,並與之在兩方面有所不同:有人主張,在JDBC應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement。
3:public interface PreparedStatement extends Statement;可以看到PreparedStatement是Statement的子接口,我們在執行查詢或者更新數據表數據的時候,拼寫SQL語句是一個很費力並且容易出錯的事情,PreparedStatement可以簡化這樣的一個過程.
4:使用Statement需要進行拼寫SQl語句,辛苦並且容易出錯,之前使用Statement的SQL語句的形式是這樣的
Class.forName("org.postgresql.Driver");
conn = DriverManager.getConnection(url, usr, psd);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select id,name from tablemame where id = 1");
while (rs.next()) {
rs.getString(1));
rs.getString(2));
}
rs.close();
st.close();
conn.close();
5:使用PreparedStatement:是Statement的子接口,可以傳入帶佔位符的SQL語句,提供了補充佔位符變量的方法
PreparedStatement的特點
PreparedStatemant,是處理預編譯語句的一個接口,PreparedStatemant可用於執行動態的SQL語句,所謂動態SQL語句,就是可以在SQL語句中提供參數,這是我們可以對相同的SQL語句替換參數從而多次使用。因此當一個SQL語句需要執行多次時,使用預編譯語句可以減少執行時間。
String sql = "select id,name from tablename where id = ?";
PreparedStatement perstmt=conn.prepareStatement(sql);
//注入參數
perstmt.setInt(1,1);
ResultSet rs = perstmt.executeQuery();
while (rs.next()) {
rs.getString(1));
rs.getString(2));
}
rs.close();
perstmt.close();
conn.close();
4:代碼分析
在上述對數據庫進行增刪改查的過程中,可以發現其共性部分,即通用的流程:
(1)創建Connection對象、SQL查詢命令字符串;
(2)對Connection對象傳入SQL查詢命令,獲得PreparedStatement對象;
(3)對PreparedStatement對象執行executeUpdate()或executeQurey()獲得結果;
(4)先後關閉PreparedStatement對象和Connection對象。
可見,使用JDBC時,最常打交道的是Connection、PreparedStatement這兩個類,以及select中的ResultSet類。
5:JDBC的API
Statement:適合只執行一次或極少執行的sql文。
PreparedStatement:適合執行需要傳參並且會多次執行的sql文,並且一定程度上防止了sql注入。
CallableStatement:適合執行存儲過程。
5.1:JDBC對於存儲過程的訪問
以上兩種語法中,對於ORACLE來說,前者用於函數調用,後者用於存儲過程調用; 在以上訪問中,返回值類型和輸出類型的參數一樣處理;輸入類型的參數另外處理;不過對於大多數的數據庫產品,在JDBC中,都不能訪問函數;
實例:
創建一個存儲過程,傳遞emp表中的一個empno,返回員工的姓名和薪水;
create or replace procedure getinfo(id in emp.empno%type,
name out emp.ename%type,salary out emp.sal%type)
is
begin
select ename,sal into name,salary from emp where empno=id;
end;
java代碼:
package com.javakc.jdbc.sql.test;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import com.javakc.jdbc.sql.utils.Db;
import oracle.jdbc.internal.OracleTypes;
public final class MyApp {
public final static void main(String[] args) {
Connection conn = Db.getConnection();
CallableStatement cstmt = null;
try {
//創建一個調用數據庫存儲過程的 CallableStatement對象
cstmt = conn.prepareCall("{call getinfo(?,?,?)}");
//這兩個是返回的值,註冊的時候先佔位
cstmt.registerOutParameter(2, OracleTypes.VARCHAR);
cstmt.registerOutParameter(3, OracleTypes.NUMBER);
cstmt.setObject(1, 7788);
//執行
cstmt.execute();
System.out.println("姓名: " + cstmt.getObject(2));
System.out.println("薪水: " + cstmt.getObject(3));
} catch (SQLException e) {
e.printStackTrace();
} finally {
Db.close(cstmt, conn);
}
}
}
6:JDBC的一般工作流程
(6.1)加載驅動
Class.forName(“org.postgresql.Driver”);
JAVA規範中明確規定:所有的驅動程序必須在靜態初始化代碼塊中將驅動註冊到驅動程序管理器中。
(6.2)建立連接
conn=DriverManager.getConnection("jdbc:postgresql://localhost:5432/pgsqltest","postgres", "2016");
Connection連接是通過DriverManager的靜態方法getConnection(.....)來得到的,這個方法的實質是把參數傳到實際的Driver中的connect()方法中來獲得數據庫連接的。
postgreSQL URL的格式:jdbc:postgresql:(協議)@XXX.XXX.X.XXX:XXXX(IP地址及端口號):XXXXXXX(所使用的庫名)
MySql URL的寫法 例:jdbc:mysql://192.168.8.21:3306/test
(6.3)獲得Statement對象
Statement stmt = conn.createStatement();
(6.4)執行sql語句
stmt.executeQuery(String sql); //返回一個查詢結果集。
stmt.executeUpdate(String sql); //返回值爲int型,表示影響記錄的條數。
將sql語句通過連接發送到數據庫中執行,以實現對數據庫的操作。
(6.5)處理結果集
使用Connection對象獲得一個Statement,Statement中的executeQuery(Stringsql) 方法可以使用select語句查詢,並且返回一個結果集。 ResultSet,通過遍歷這個結果集,可以獲得select語句的查尋結果,ResultSet的next()方法會操作一個遊標從第一條記錄的前面開始讀取,直到最後一條記錄。
executeUpdate(String sql) 方法用於執行DDL和DML語句,比如可以update,delete操作。
只有執行select語句纔有結果集返回。
Statement str=con.createStatement(); //創建Statement
String sql=”insert into test(id,name)values(1,”+”’”+”test”+”’”+”)”;
str. executeUpdate(sql);//執行Sql語句
String sql=”select * from test”;
ResultSet rs=str. executeQuery(String sql);//執行Sql語句,執行select語句後有結果集
//遍歷處理結果集信息
while(rs.next()){
System.out.println(rs.getInt(“id”));
System.out.println(rs.getString(“name”))
}
(6.6)關閉數據庫連接
rs.close();
stmt.close();
con.close();
ResultSet Statement Connection是依次依賴的。
7:JDBC事務
事務的4大特性
(7.1) 原子性
事務的原子性指的是,事務中包含的程序作爲數據庫的邏輯工作單位,它所做的對數據修改操作要麼全部執行,要麼完全不執行。
原子操作,也就是不可分割的操作,必須一起成功一起失敗。
(7.2) 一致性
事務的一致性指的是在一個事務執行之前和執行之後數據庫都必須處於一致性狀態。這種特性稱爲事務的一致性。假如數據庫的狀態滿足所有的完整性約束,就說該數據庫是一致的。
(7.3) 分離性
分離性指併發的事務是相互隔離的。即一個事務內部的操作及正在操作的數據必須封鎖起來,不被其它企圖進行修改的事務看到。
(7.4) 持久性
持久性意味着當系統或介質發生故障時,確保已提交事務的更新不能丟失。即一旦一個事務提交,DBMS保證它對數據庫中數據的改變應該是永久性的,耐得住任何系統故障。持久性通過數據庫備份和恢復來保證。
代碼: