14.JDBC原理介紹及增刪改查示範
阿新 • • 發佈:2019-02-05
本文為《Spark大型電商專案實戰》 系列文章之一,主要介紹JDBC的原理以及對MySQL資料庫增刪改查的具體實現過程。
JDBC原理介紹
JDBC代表了JDK提供的一套面向資料庫的一套開發介面,大部分僅僅是介面而已,Java應用程式光有JDBC是操作不了資料庫的,更不用談增刪改查等功能。JDBC真正的意義在於通過介面統一了java程式對各種資料庫的訪問規範。
資料庫廠商會提供JDBC驅動:JDBC Driver,在這套實現類中,不同的資料廠商就實現了針對自己資料庫的一套連線、執行SQL語句等等實際的功能。
本次實驗專案主要使用的是MySQL資料庫,以下例子是針對MySQL資料庫開發。
實現增刪改查功能
在包com.erik.sparkproject.test
中建立類JdbcCRUD.java
,實現對MySQL資料庫的增刪改查功能,程式碼如下:
package com.erik.sparkproject.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC增刪改查
* @author Erik
*
*/
public class JdbcCRUD {
public static void main(String[] args) {
// TODO Auto-generated method stub
//insert();
//update();
//delete();
//select();
preparedStatement();
}
/**
* 測試插入資料
*/
private static void insert() {
//引用JDBC相關的所有介面或者是抽象類的時候,必須是引用java.sql包下的
//java.sql包下的,才代表了java提供的JDBC介面,只是一套規範
Connection conn = null;
//定義SQL語句執行控制代碼:Statement物件
//Statement物件其實就是底層基於Connection資料庫連線
Statement stmt = null;
try {
//第一步,載入資料庫驅動
//使用Class.forName()方式載入資料庫的驅動類
//Class.forName()是Java提供的一種基於反射的方式,直接根據類的全限定名(包+類)
//從類所在的磁碟檔案(.class檔案)中載入類對應的內容,並建立對應的class物件
Class.forName("com.mysql.jdbc.Driver");
//獲取資料庫的連線
//使用DriverManager.getConnection()方法獲取針對資料庫的連線
//需要給方法傳入三個引數,包括url、user、password
//其中url就是有特定格式的資料庫連線串,包括“主協議:子協議“//主機名:埠號//資料庫”
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sparkproject",
"root",
"****");//這裡根據實際情況填寫本地MySQL資料庫root密碼
//基於資料庫連線的Connection物件,建立SQL語句執行控制代碼,Statement物件
//Statement物件 ,就是用於基於底層的Connection代表的資料庫連線
//允許我們通過Java程式,通過Statement物件,向MySQL資料庫傳送SQL語句
//從而實現通過傳送的SQL語句來執行增刪改查等邏輯
stmt = conn.createStatement();
//基於Statement物件,來執行insert SQL語句插入一條資料
//Statement.executeUpdate()方法可以用來執行insert、update、delete語句
//返回型別是int值,也就是SQL語句影響的行數
//String sql = "insert into test_user(name,age) values('張三',25)";
String sql = "insert into test_user(name,age) values('李四',26)";
int rtn = stmt.executeUpdate(sql);
System.out.println("SQL語句影響了【"+rtn+"】行。");
}catch (Exception e){
e.printStackTrace();
} finally {
//最後一定要記得在finally程式碼塊中,儘快在執行完SQL語句之後,就釋放資料庫連線
try {
if(stmt != null){
stmt.close();
}
if(conn != null){
conn.close();
}
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}
}
/**
* 測試更新資料
*/
private static void update() {
Connection conn =null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sparkproject",
"root",
"erik");
stmt = conn.createStatement();
String sql = "update test_user set age=27 where name='李四'";
int rtn = stmt.executeUpdate(sql);
System.out.println("SQL語句影響了【"+rtn+"】行。");
}catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
if(conn != null)
conn.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
/**
* 測試刪除資料
*/
private static void delete() {
Connection conn =null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sparkproject",
"root",
"erik");
stmt = conn.createStatement();
String sql = "delete from test_user where name='李四'";
int rtn = stmt.executeUpdate(sql);
System.out.println("SQL語句影響了【"+rtn+"】行。");
}catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
if(conn != null)
conn.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
/**
* 測試查詢資料
*/
private static void select() {
Connection conn = null;
Statement stmt = null;
//對於select查詢語句,需要定義ResultSet
//ResultSet代表了select語句查詢出來的資料
//需要通過ResutSet物件,來遍歷查詢出來的每一條資料,然後對資料進行儲存或者處理
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sparkproject",
"root",
"erik");
stmt = conn.createStatement();
String sql = "select * from test_user";
rs = stmt.executeQuery(sql);
//獲取到ResultSet以後,就要對其進行遍歷,然後獲取查詢出來的每一條資料
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
System.out.println("id="+id+",name="+name+",age="+age);
}
}catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stmt != null){
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 使用Statement時,必須在SQL語句中,實際地區嵌入值,容易發生SQL注入
* 而且效能低下
*
* 使用PreparedStatement,就可以解決上述的兩個問題
* 1.SQL主任,使用PreparedStatement時,是可以在SQL語句中,對值所在的位置使用?這種佔位符,
* 實際的值是放在陣列中的引數,PreparedStatement會對數值做特殊處理,往往處理後會使惡意注入的SQL程式碼失效。
* 2.提升效能,使用P熱怕熱的Statement後,結構類似的SQL語句會變成一樣的,因為值的地方會變成?,
* 一條SQL語句,在MySQL中只會編譯一次,後面的SQL語句過來,就直接拿編譯後的執行計劃加上不同的引數直接執行,
* 可以大大提升效能
*/
private static void preparedStatement() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/sparkproject?characterEncoding=utf8",
"root",
"erik");
//第一個,SQL語句中,值所在的地方,都用問號代表
String sql = "insert into test_user(name,age) values(?,?)";
pstmt = conn.prepareStatement(sql);
//第二個,必須呼叫PreparedStatement的setX()系列方法,對指定的佔位符賦值
pstmt.setString(1, "李四");
pstmt.setInt(2, 26);
//第三個,執行SQL語句時,直接使用executeUpdate()即可
int rtn = pstmt.executeUpdate();
System.out.println("SQL語句影響了【"+rtn+"】行。");
}catch (Exception e){
e.printStackTrace();
} finally {
try {
if(pstmt != null){
pstmt.close();
}
if(conn != null){
conn.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
使用以上程式碼可以對本地MySQL資料庫實現增刪改查等功能。
總結
JDBC最基本的使用過程:
1. 載入驅動類:Class.forName()
2. 獲取資料庫連線:DriverManager.getConnection()
3. 建立SQL語句執行控制代碼:Connection.createStatement()
4. 執行SQL語句:Statement.executeUpdate()
5. 釋放資料庫連線資源:finally,Connection.close()