Java使用JDBC連接數(shù)據(jù)庫的詳細(xì)步驟
一、JDBC是什么?
JDBC 指 Java 數(shù)據(jù)庫連接(Java Database Connectivity),是一種標(biāo)準(zhǔn)Java應(yīng)用編程接口( JAVA API),JDBC就是一套sun公司定義的接口,JDBC本質(zhì)上就是Sun公司制定的一套接口(interface)!每個(gè)數(shù)據(jù)庫廠商需要實(shí)現(xiàn)這套接口。我們只需要調(diào)用需要即可用來連接 Java 編程語言和廣泛的數(shù)據(jù)庫。
JDBC API 庫包含下面提到的每個(gè)任務(wù),都是與數(shù)據(jù)庫相關(guān)的常用用法。
- 制作到數(shù)據(jù)庫的連接。
- 創(chuàng)建 SQL 或 MySQL 語句。
- 執(zhí)行 SQL 或 MySQL 查詢數(shù)據(jù)庫。
- 查看和修改所產(chǎn)生的記錄。
從根本上來說,JDBC 是一種規(guī)范,它提供了一套完整的接口,允許便攜式訪問到底層數(shù)據(jù)庫,因此可以用 Java 編寫不同類型的可執(zhí)行文件,例如:
- Java 應(yīng)用程序
- Java Applets
- Java Servlets
- Java ServerPages (JSPs)
- Enterprise JavaBeans (EJBs)
所有這些不同的可執(zhí)行文件就可以使用 JDBC 驅(qū)動(dòng)程序來訪問數(shù)據(jù)庫,這樣可以方便的訪問數(shù)據(jù)。
JDBC 具有 ODBC 一樣的性能,允許 Java 程序包含與數(shù)據(jù)庫無關(guān)的代碼。
二、使用步驟
1.注冊(cè)驅(qū)動(dòng)
數(shù)據(jù)庫廠商的Java程序員所寫的實(shí)現(xiàn)類 叫做驅(qū)動(dòng) Driver
注冊(cè)驅(qū)動(dòng)
第一種注冊(cè)方法代碼如下:(不常用)
public class 注冊(cè)驅(qū)動(dòng) { public static void main(String[] args) { try { DriverManager.registerDriver(new com.mysql.jdbc.Driver()); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
第二種方利用反射的特性,加載過程中注冊(cè)驅(qū)動(dòng)的過程。
關(guān)于反射的補(bǔ)充: Java中的靈魂-反射機(jī)制
關(guān)于JDBC—MySQL中以類加載的方式注冊(cè)驅(qū)動(dòng)(反射)詳解鏈接:
JDBC—MySQL以類加載的方式注冊(cè)驅(qū)動(dòng)(反射)
class.forName(com.mysql.jdbc.Driver);
上述一行代碼就可以通過反射這個(gè)動(dòng)作調(diào)用類,實(shí)現(xiàn)Driver類的加載 但是需要使用try和catch語句塊環(huán)繞
2.獲取連接
要連接數(shù)據(jù)庫的url---- String url="jdbc:mysql://localhost:3306/test?"+ "useUnicode=true&characterEncoding=UTF8";//防止亂碼
要連接數(shù)據(jù)庫的用戶名---- String user="xxxx";
要連接數(shù)據(jù)庫的密碼---- String pass="xxxx";
接下來我們分析下url:
"jdbc(這是協(xié)議以jdbc開頭):mysql(這是子協(xié)議,數(shù)據(jù)庫管理系統(tǒng)稱)://localhost(數(shù)據(jù)庫來源地址):3306(目標(biāo)端口)/test(要查詢的表的表名)?"
"useUnicode=true&characterEncoding=UTF8";添加這個(gè)是為了防止亂碼,指定使用Unicode字符集 ,且使用UTF-8來編輯。
/* url包括哪幾部分: 協(xié)議 IP Port 資源名 eg:http://180.101.49.11:80/index.html http:// 通信協(xié)議 180.101.49.11 IP地址 80 端口號(hào) index.html 資源名 */
// 2、獲取連接 /* url包括哪幾部分: 協(xié)議 IP Port 資源名 eg:http://180.101.49.11:80/index.html http:// 通信協(xié)議 180.101.49.11 IP地址 80 端口號(hào) index.html 資源名 */ // static Connection getConnection(String url, String user, String password) String url = "jdbc:mysql://127.0.0.1:3306/hello"; String user = "root"; System.out.println(" "); String password = "rota"; conn = DriverManager.getConnection(url,user,password); System.out.println("數(shù)據(jù)庫連接對(duì)象 : " + conn); //數(shù)據(jù)庫連接對(duì)象com.mysql.jdbc.JDBC4Connection@1ae369b7
3.獲取數(shù)據(jù)庫操作對(duì)象
// 3、獲取數(shù)據(jù)庫操作對(duì)象 // Statement 類中 createStatement() 創(chuàng)建一個(gè) Statement 對(duì)象來將 SQL 語句發(fā)送到數(shù)據(jù)庫。 stmt = conn.createStatement(); // 4、執(zhí)行sql語句 // int executeUpdate(String sql) // 專門執(zhí)行DML語句 // 返回值是“影響數(shù)據(jù)庫中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗");
4.執(zhí)行sql語句
// 4、執(zhí)行sql語句 // int executeUpdate(String sql) // 專門執(zhí)行DML語句 // 返回值是“影響數(shù)據(jù)庫中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗");
5.處理查詢結(jié)果集
rs = stmt.executeQuery("select empno,ename,sal from emp"); while(rs.next()){ /* String empno = rs.getString(1); String ename = rs.getString(2); String sal = rs.getString(3); System.out.println(empno + "," + ename + "," + sal); */ /* // 按下標(biāo)取出,程序不健壯 String empno = rs.getString("empno"); String ename = rs.getString("ename"); String sal = rs.getString("sal"); System.out.println(empno + "," + ename + "," + sal); */ /* // 以指定的格式取出 int empno = rs.getInt(1); String ename = rs.getString(2); double sal = rs.getDouble(3); System.out.println(empno + "," + ename + "," + (sal + 100)); */ int empno = rs.getInt("empno"); String ename = rs.getString("ename"); double sal = rs.getDouble("sal"); System.out.println(empno + "," + ename + "," + (sal + 200)); }
其中執(zhí)行增刪改的方法返回值是int類型
執(zhí)行查詢的方法返回值是操作結(jié)果集對(duì)象,即使ResultSet的實(shí)例化對(duì)象!
6.釋放資源
finally { // 6、釋放資源 // 從小到大依次關(guān)閉 //finally語句塊內(nèi)的語句一定會(huì)執(zhí)行! if(stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
上述六步連貫:
第一次優(yōu)化:(比較兩種注冊(cè)驅(qū)動(dòng)的方法)
import java.sql.*; public class JDBCTest01 { public static void main(String[] args) { Connection conn = null; Statement stmt = null;//先創(chuàng)建連接對(duì)象 和 操作對(duì)象 并且引用為空,是為了對(duì)象變量的生命周期不僅僅局限于try語句塊內(nèi),而是在整個(gè)main方法內(nèi),方便后續(xù)finally語句塊內(nèi)釋放資源 try{ // 1、注冊(cè)驅(qū)動(dòng) Driver driver = new com.mysql.jdbc.Driver(); //多態(tài),父類型引用指向子類型對(duì)象 DriverManager.registerDriver(driver); // 2、獲取連接 /* url包括哪幾部分: 協(xié)議 IP Port 資源名 eg:http://180.101.49.11:80/index.html http:// 通信協(xié)議 180.101.49.11 IP地址 80 端口號(hào) index.html 資源名 */ // static Connection getConnection(String url, String user, String password) String url = "jdbc:mysql://127.0.0.1:3306/hello"; String user = "root"; System.out.println(" "); String password = "rota"; conn = DriverManager.getConnection(url,user,password); System.out.println("數(shù)據(jù)庫連接對(duì)象 : " + conn); //數(shù)據(jù)庫連接對(duì)象com.mysql.jdbc.JDBC4Connection@1ae369b7 // 3、獲取數(shù)據(jù)庫操作對(duì)象 // Statement 類中 createStatement() 創(chuàng)建一個(gè) Statement 對(duì)象來將 SQL 語句發(fā)送到數(shù)據(jù)庫。 stmt = conn.createStatement(); // 4、執(zhí)行sql語句 // int executeUpdate(String sql) // 專門執(zhí)行DML語句 // 返回值是“影響數(shù)據(jù)庫中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗"); // 5、處理查詢結(jié)果集 } catch(SQLException e) { e.printStackTrace(); } finally { // 6、釋放資源 // 從小到大依次關(guān)閉 //finally語句塊內(nèi)的語句一定會(huì)執(zhí)行! if(stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
第二次優(yōu)化:(比較兩種注冊(cè)驅(qū)動(dòng)的方法)
package com.zdx.source.code.jdbc; /* JDBC完成Delete */ import java.sql.*; public class JDBCTest02 { public static void main(String[] args) { // 1、注冊(cè)驅(qū)動(dòng) // 2、獲取連接 // 3、獲取數(shù)據(jù)庫操作對(duì)象 // 4、執(zhí)行sql語句 // 5、獲取查詢結(jié)果集 // 6、釋放資源 Connection conn = null; Statement stmt = null; try { Driver driver = new com.mysql.jdbc.Driver(); DriverManager.registerDriver(driver); String url = "jdbc:mysql://127.0.0.1:3306/mydatabase"; String user = "root"; String password = "146"; conn = DriverManager.getConnection(url,user,password); stmt = conn.createStatement(); int count = stmt.executeUpdate("delete from dept where deptno = 50"); System.out.println(count == 1? "刪除成功":"刪除失敗"); } catch(SQLException e){ e.printStackTrace(); } finally { if(conn != null) { try { conn.close(); } catch(SQLException e){ e.printStackTrace(); } } if(stmt != null) { try { stmt.close(); } catch(SQLException e){ e.printStackTrace(); } } } } }
第三次優(yōu)化:(最佳注冊(cè)驅(qū)動(dòng)獲取連接)
package com.zdx.source.code.jdbc; /* 注冊(cè)驅(qū)動(dòng)的另一種方式 */ import java.sql.*; public class JDBCTest03 { public static void main(String[] args) { try{ // 注冊(cè)驅(qū)動(dòng) Class.forName("com.mysql.jdbc.Driver"); // 獲取連接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase","root","146"); System.out.println(conn); } catch(SQLException e){ e.printStackTrace(); } catch(ClassNotFoundException e){ e.printStackTrace(); } } }
第四次優(yōu)化:(使用資源綁定器)
package com.zdx.source.code.jdbc; /* 使用資源綁定器 */ import java.sql.*; import java.util.*; public class JDBCTest04 { public static void main(String[] args) { ResourceBundle bundle = ResourceBundle.getBundle("jdbc"); String driver = bundle.getString("driver"); String url = bundle.getString("url"); String user = bundle.getString("user"); String password = bundle.getString("password"); Connection conn = null; Statement stmt = null; try { Class.forName(driver); conn = DriverManager.getConnection(url,user,password); stmt = conn.createStatement(); int count = stmt.executeUpdate("insert into dept(deptno,dname,loc) values(50,'人事部','北京');"); System.out.println(count == 1? "保存成功":"保存失敗"); } catch(SQLException e){ e.printStackTrace(); } catch(ClassNotFoundException e) { e.printStackTrace(); } finally { if(conn != null) { try { conn.close(); } catch(SQLException e){ e.printStackTrace(); } } if(stmt != null) { try { stmt.close(); } catch(SQLException e){ e.printStackTrace(); } } } } }
第五次優(yōu)化:(對(duì)操作結(jié)果集的處理)
package com.zdx.source.code.jdbc; /* 執(zhí)行DQL語句 */ import java.sql.*; import java.util.*; public class JDBCTest05 { public static void main(String[] args) { // 1、注冊(cè)驅(qū)動(dòng) // 2、建立連接 // 3、獲取數(shù)據(jù)庫操作對(duì)象 // 4、執(zhí)行sql語句 // 5、獲取查詢結(jié)果集 // 6、釋放資源 Connection conn = null; Statement stmt = null; ResultSet rs = null; try{ ResourceBundle rb = ResourceBundle.getBundle("jdbc"); String driver = rb.getString("driver"); String url = rb.getString("url"); String user = rb.getString("user"); String password = rb.getString("password"); Class.forName(driver); conn = DriverManager.getConnection(url,user,password); stmt = conn.createStatement(); rs = stmt.executeQuery("select empno,ename,sal from emp"); while(rs.next()){ /* String empno = rs.getString(1); String ename = rs.getString(2); String sal = rs.getString(3); System.out.println(empno + "," + ename + "," + sal); */ /* // 按下標(biāo)取出,程序不健壯 String empno = rs.getString("empno"); String ename = rs.getString("ename"); String sal = rs.getString("sal"); System.out.println(empno + "," + ename + "," + sal); */ /* // 以指定的格式取出 int empno = rs.getInt(1); String ename = rs.getString(2); double sal = rs.getDouble(3); System.out.println(empno + "," + ename + "," + (sal + 100)); */ int empno = rs.getInt("empno"); String ename = rs.getString("ename"); double sal = rs.getDouble("sal"); System.out.println(empno + "," + ename + "," + (sal + 200)); } } catch(Exception e){ e.printStackTrace(); }finally{ if(rs != null){ try{ rs.close(); } catch (Exception e){ e.printStackTrace(); } } if(stmt != null){ try{ stmt.close(); } catch (Exception e){ e.printStackTrace(); } } if(conn != null){ try{ conn.close(); } catch (Exception e){ e.printStackTrace(); } } } } }
總結(jié):
在上述五次優(yōu)化代碼的過程中,針對(duì)這六步
// 1、注冊(cè)驅(qū)動(dòng) // 2、獲取連接 // 3、獲取數(shù)據(jù)庫操作對(duì)象 // 4、執(zhí)行sql語句 // 5、獲取查詢結(jié)果集 // 6、釋放資源
第一步的注冊(cè)驅(qū)動(dòng)最終使用了反射,已達(dá)最優(yōu)
第二步的獲取連接已達(dá)最優(yōu),已經(jīng)有能力去完成JDBC連接數(shù)據(jù)庫的工具類的封裝了
看到這里可以移步去學(xué)習(xí)—————>工具類的封裝啦!
注:
第三步的獲取數(shù)據(jù)庫操作對(duì)象中我們是使用Statement接口
public interface Statement extends Wrapper, AutoCloseable
還可以優(yōu)化成為PreparedStatement
public interface PreparedStatement extends Statement
在實(shí)際開發(fā)過程中由于PreparedStatement能防止注入,且預(yù)先編譯SQL語句的特性使得程序健壯性提高,所以實(shí)際開發(fā)中99.9%使用PreparedStatement。這是后話,由于封裝工具類主要封裝的是注冊(cè)驅(qū)動(dòng),獲取連接和釋放資源,后續(xù)將專門寫一篇博客討論P(yáng)reparedStatement
此外在實(shí)際開發(fā)中除了掌握上述六步還需要掌握事務(wù)提交回滾三部曲。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java實(shí)現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信)
這篇文章主要介紹了java實(shí)現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10hibernate 配置數(shù)據(jù)庫方言的實(shí)現(xiàn)方法
這篇文章主要介紹了hibernate 配置數(shù)據(jù)庫方言的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05IntelliJ IDEA 編輯器的全局搜索中使用正則表達(dá)式的操作方法
這篇文章主要介紹了IntelliJ IDEA 編輯器的全局搜索中使用正則表達(dá)式的相關(guān)知識(shí),補(bǔ)充介紹了IDEA查找和替換實(shí)用正則,感興趣的朋友跟隨小編一起看看吧2024-01-01SpringMVC高級(jí)開發(fā)功能實(shí)現(xiàn)過程解析
這篇文章主要介紹了SpringMVC高級(jí)開發(fā)功能實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Java如何通過枚舉實(shí)現(xiàn)有限狀態(tài)機(jī)
這篇文章主要介紹了Java如何通過枚舉實(shí)現(xiàn)有限狀態(tài)機(jī),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07