JavaEE學習日誌持續更新----> 必看!JavaEE學習路線(文章總彙)
Java學習日誌(三十二)
JDBC
JDBC的概念和原理
JDBC使用步驟
JDBC:使用java程序執行sql語句,對數據庫表進行增刪改查(CURD)
使用步驟:固定
-
註冊驅動,告之JVM我們使用的是哪種數據庫驅動程序(mysql,oracle…)
-
獲取數據庫連接對象
Connection
java程序:TCP客戶端 數據庫:TCP服務器 使用客戶端訪問服務器,和服務器經過3次握手建立一個連接通路 這個連接通路中有一個IO流對象,用於客戶端和服務器交互數據
-
獲取執行者對象
Statement
,用於執行sql語句,把sql語句發送到數據庫中執行 -
執行sql語句,獲取結果集
- 增刪改:int affected(受影響的) 影響數據庫的有效行數
- 查詢:ResultSet結果集,把查詢的多行結果存儲到一個結果集中 -
處理結果集
- 增刪改:不用處理
- 查詢:遍歷結果集 -
釋放資源
注意:1,2,3,6固定不變,4,5根據增刪改查不同而不同
第一步:註冊驅動
使用java.sql.DriverManager
類中的方法實現:管理一組JDBC驅動程序的基本服務。
靜態方法:
static void registerDriver(Driver driver)
使用 DriverManager註冊給定的驅動程序。
參數:
java.sql.Driver:是一個接口,每個驅動程序類必須實現的接口。
傳遞Driver接口的實現類對象,由mysql驅動提供
com.mysql.jdbc.Driver
public class Demo01JDBC {
public static void main(String[] args) throws SQLException {
DriverManager.registerDriver(new Driver());
}
}
查看com.mysql.jdbc.Driver
的源碼發現,有一個靜態代碼塊,已經註冊了驅動,我們再註冊一個驅動,就註冊了兩次,會產生浪費。
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
解決方案:使用反射技術,獲取class文件,會執行類中的靜態代碼塊
格式:Class.forName("foo.bah.Driver")
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
}
}
第二步:獲取數據庫連接對象Connection
使用java.sql.DriverManager類
中的方法實現
靜態方法:
static Connection getConnection(String url, String user, String password)
嘗試建立與給定數據庫URL的連接。
參數:
String url:數據庫服務器的地址,固定格式
- jdbc:mysql://ip:端口號/數據庫名稱
- jdbc:mysql://localhost:3306/day03
String user:數據庫用戶名
String password:數據庫密碼
返回值:
java.sql.Connection是一個接口,返回的是Connection接口的實現類對象
由mysql驅動提供,我們可以使用Connection接口來接收這個實現類對象(多態)
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
}
}
第三步:獲取執行者對象Statement
使用Connection接口
中提供的方法實現:
Statement createStatement()
創建一個 Statement對象,用於將SQL語句發送到數據庫。
返回值:
java.sql.Statement是一個接口,返回的是Statement接口的實現類對象
由mysql驅動提供,我們可以使用Statement接口來接收這個實現類對象(多態)
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
}
}
第四步:執行sql語句,獲取結果集
使用Statement接口
中的方法實現:
int executeUpdate(String sql)
執行給定的SQL語句,這可能是 INSERT , UPDATE ,或 DELETE語句,或者不返回任何內容,如SQL DDL語句的SQL語句。ResultSet executeQuery(String sql)
執行給定的SQL語句,該語句可能爲SELECT
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id) "+
"VALUES('p012','鍵盤',500,'1','c001');");
}
}
完整代碼
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id) "+
"VALUES('p012','鍵盤',500,'1','c001');");
//5.處理結果集
System.out.println(row);//1
//6.釋放資源
stat.close();
conn.close();
}
}
創建JDBCUtils工具類並測試
創建JDBC工具類,工具類中的方法都是靜態方法,方便直接通過類名使用
- 定義一個靜態方法,獲取Collection對象並返回
- 定義一個靜態方法,釋放資源
代碼示例:JDBCUtils工具類創建
import java.sql.*;
public class JDBCUtils {
//定義4個靜態的成員變量,用於存儲數據庫連接的相關信息
//註冊驅動的地址
private static String driver = "com.mysql.jdbc.Driver";
//數據庫的url地址
private static String url = "jdbc:mysql://localhost:3306/day03";
//數據庫用戶名
private static String user = "root";
//數據庫的密碼
private static String password = "root";
//靜態代碼塊:優先執行,只執行一次
static {
//註冊驅動
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//定義一個靜態方法,獲取Collection對象並返回
public static Connection getConnection(){
Connection conn = null;
try {
//獲取Connection對象並返回
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
/*
如果獲取數據庫連接對象失敗,那麼程序就沒有必要繼續執行了
所以可以把編譯異常轉換爲運行時異常,讓程序停止下來
*/
throw new RuntimeException("獲取數據庫連接對象失敗"+e);
}
return conn;
}
//定義一個靜態方法,釋放資源
public static void close(ResultSet rs, Statement stat, Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
測試類
/*
測試JDBCUtils工具類
*/
public class Demo02testJDBCUtils {
public static void main(String[] args) {
//使用JDBCUtil工具類中的方法getConnection獲取數據庫連接對象
Connection conn = JDBCUtils.getConnection();
System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@256216b3
}
}
使用JDBC技術對數據庫進行操作
增刪改
@Test
public void testInsert() {
//使用JDBCUtils工具類中的方法getConnection獲取數據庫連接對象
Connection conn = JDBCUtils.getConnection();
//獲取執行者對象
Statement stat = null;
try {
stat = conn.createStatement();
//執行sql語句,獲取結果
//增加數據
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id)"+
" VALUES('p014','鼠標',500,'1','c001'),('p015','鼠標',500,'1','c001');");
//修改數據
//int row = stat.executeUpdate("UPDATE products SET price = 7999 WHERE pid = 'p013';");
//刪除數據
//int row = stat.executeUpdate("DELETE from products where pid in('p001','p002','p003');");
//處理結果
System.out.println(row+"行數據添加成功!");
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放資源
JDBCUtils.close(null,stat,conn);
}
}
查詢
執行sql語句,獲取結果集:
ResultSet executeQuery(String sql)
執行給定的SQL語句,該語句可能爲SELECT
返回值:
java.sql.ResultSet是一個接口,返回的是ResultSet接口的實現類對象。
由mysql驅動提供,我們可以使用ResultSet接口來接收這個實現類對象(多態)
處理結果集,遍歷結果集:和迭代器的使用方式一模一樣
- ResultSet中有一個方法叫next判斷有沒有下一行數據;有返回true,沒用返回false
boolean next()
將光標從當前位置向前移動一行。 - ResultSet中有一個方法叫getXXX(列的索引/列名)取出結果
int getInt(int columnIndex)
:列的索引,從1開始
int getInt(String columnLabel)
:列名
注意:數據庫的列是什麼類型,就用get類型的方法獲取這個字段
也可以使用getObject
來獲取所有類型的字段,返回值是Object類型
代碼示例:
@Test
public void testSelect() throws SQLException {
//使用JDBCUtils工具類中的方法getConnection獲取數據庫連接對象
Connection conn = JDBCUtils.getConnection();
//獲取執行者對象
Statement stat = conn.createStatement();
/*
執行sql語句,獲取結果集
ResultSet executeQuery(String sql) 執行給定的SQL語句,該語句可能爲SELECT
返回值:
java.sql.ResultSet是一個接口,返回的是ResultSet接口的實現類對象
由mysql驅動提供,我們可以使用ResultSet接口來接收這個實現類對象(多態)
*/
ResultSet rs = stat.executeQuery("select * from products;");
//System.out.println(rs);//com.mysql.jdbc.JDBC42ResultSet@3224f60b
/*
處理結果集,遍歷結果集
和迭代器的使用方式一模一樣
ResultSet中有一個方法叫next判斷有沒有下一行數據;有返回true,沒用返回false
boolean next() 將光標從當前位置向前移動一行。
ResultSet中有一個方法叫getXXX(列的索引/列名)取出結果
int getInt(int columnIndex):列的索引,從1開始
int getInt(String columnLabel):列名
注意:數據庫的列是什麼類型,就用get類型的方法獲取這個字段
也可以使用getObject來獲取所有類型的字段,返回值是Object類型
*/
while(rs.next()){
/*String pid = rs.getString(1);
String pname = rs.getString(2);
int price = rs.getInt(3);
String flag = rs.getString(4);
String category_cid = rs.getString(5);*/
String pid = rs.getString("pid");
String pname = rs.getString("pname");
int price = rs.getInt("price");
String flag = rs.getString("flag");
String category_cid = rs.getString("category_id");
System.out.println(pid+"\t"+pname+"\t"+price+"\t"+flag+"\t"+category_cid);
}
//釋放資源
JDBCUtils.close(rs,stat,conn);
}
執行結果