Java使用JDBC連接數(shù)據(jù)庫(kù)的詳細(xì)步驟
一、JDBC是什么?
JDBC 指 Java 數(shù)據(jù)庫(kù)連接(Java Database Connectivity),是一種標(biāo)準(zhǔn)Java應(yīng)用編程接口( JAVA API),JDBC就是一套sun公司定義的接口,JDBC本質(zhì)上就是Sun公司制定的一套接口(interface)!每個(gè)數(shù)據(jù)庫(kù)廠商需要實(shí)現(xiàn)這套接口。我們只需要調(diào)用需要即可用來(lái)連接 Java 編程語(yǔ)言和廣泛的數(shù)據(jù)庫(kù)。
JDBC API 庫(kù)包含下面提到的每個(gè)任務(wù),都是與數(shù)據(jù)庫(kù)相關(guān)的常用用法。
- 制作到數(shù)據(jù)庫(kù)的連接。
- 創(chuàng)建 SQL 或 MySQL 語(yǔ)句。
- 執(zhí)行 SQL 或 MySQL 查詢(xún)數(shù)據(jù)庫(kù)。
- 查看和修改所產(chǎn)生的記錄。
從根本上來(lái)說(shuō),JDBC 是一種規(guī)范,它提供了一套完整的接口,允許便攜式訪(fǎng)問(wèn)到底層數(shù)據(jù)庫(kù),因此可以用 Java 編寫(xiě)不同類(lèi)型的可執(zhí)行文件,例如:
- Java 應(yīng)用程序
- Java Applets
- Java Servlets
- Java ServerPages (JSPs)
- Enterprise JavaBeans (EJBs)
所有這些不同的可執(zhí)行文件就可以使用 JDBC 驅(qū)動(dòng)程序來(lái)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù),這樣可以方便的訪(fǎng)問(wèn)數(shù)據(jù)。
JDBC 具有 ODBC 一樣的性能,允許 Java 程序包含與數(shù)據(jù)庫(kù)無(wú)關(guān)的代碼。
二、使用步驟
1.注冊(cè)驅(qū)動(dòng)
數(shù)據(jù)庫(kù)廠商的Java程序員所寫(xiě)的實(shí)現(xiàn)類(lèi) 叫做驅(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(); } } }
第二種方利用反射的特性,加載過(guò)程中注冊(cè)驅(qū)動(dòng)的過(guò)程。
關(guān)于反射的補(bǔ)充: Java中的靈魂-反射機(jī)制
關(guān)于JDBC—MySQL中以類(lèi)加載的方式注冊(cè)驅(qū)動(dòng)(反射)詳解鏈接:
JDBC—MySQL以類(lèi)加載的方式注冊(cè)驅(qū)動(dòng)(反射)
class.forName(com.mysql.jdbc.Driver);
上述一行代碼就可以通過(guò)反射這個(gè)動(dòng)作調(diào)用類(lèi),實(shí)現(xiàn)Driver類(lèi)的加載 但是需要使用try和catch語(yǔ)句塊環(huán)繞
2.獲取連接
要連接數(shù)據(jù)庫(kù)的url---- String url="jdbc:mysql://localhost:3306/test?"+ "useUnicode=true&characterEncoding=UTF8";//防止亂碼
要連接數(shù)據(jù)庫(kù)的用戶(hù)名---- String user="xxxx";
要連接數(shù)據(jù)庫(kù)的密碼---- String pass="xxxx";
接下來(lái)我們分析下url:
"jdbc(這是協(xié)議以jdbc開(kāi)頭):mysql(這是子協(xié)議,數(shù)據(jù)庫(kù)管理系統(tǒng)稱(chēng))://localhost(數(shù)據(jù)庫(kù)來(lái)源地址):3306(目標(biāo)端口)/test(要查詢(xún)的表的表名)?"
"useUnicode=true&characterEncoding=UTF8";添加這個(gè)是為了防止亂碼,指定使用Unicode字符集 ,且使用UTF-8來(lái)編輯。
/* 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ù)庫(kù)連接對(duì)象 : " + conn); //數(shù)據(jù)庫(kù)連接對(duì)象com.mysql.jdbc.JDBC4Connection@1ae369b7
3.獲取數(shù)據(jù)庫(kù)操作對(duì)象
// 3、獲取數(shù)據(jù)庫(kù)操作對(duì)象 // Statement 類(lèi)中 createStatement() 創(chuàng)建一個(gè) Statement 對(duì)象來(lái)將 SQL 語(yǔ)句發(fā)送到數(shù)據(jù)庫(kù)。 stmt = conn.createStatement(); // 4、執(zhí)行sql語(yǔ)句 // int executeUpdate(String sql) // 專(zhuān)門(mén)執(zhí)行DML語(yǔ)句 // 返回值是“影響數(shù)據(jù)庫(kù)中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷(xiāo)售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗");
4.執(zhí)行sql語(yǔ)句
// 4、執(zhí)行sql語(yǔ)句 // int executeUpdate(String sql) // 專(zhuān)門(mén)執(zhí)行DML語(yǔ)句 // 返回值是“影響數(shù)據(jù)庫(kù)中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷(xiāo)售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗");
5.處理查詢(xún)結(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類(lèi)型
執(zhí)行查詢(xún)的方法返回值是操作結(jié)果集對(duì)象,即使ResultSet的實(shí)例化對(duì)象!
6.釋放資源
finally { // 6、釋放資源 // 從小到大依次關(guān)閉 //finally語(yǔ)句塊內(nèi)的語(yǔ)句一定會(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語(yǔ)句塊內(nèi),而是在整個(gè)main方法內(nèi),方便后續(xù)finally語(yǔ)句塊內(nèi)釋放資源 try{ // 1、注冊(cè)驅(qū)動(dòng) Driver driver = new com.mysql.jdbc.Driver(); //多態(tài),父類(lèi)型引用指向子類(lè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ù)庫(kù)連接對(duì)象 : " + conn); //數(shù)據(jù)庫(kù)連接對(duì)象com.mysql.jdbc.JDBC4Connection@1ae369b7 // 3、獲取數(shù)據(jù)庫(kù)操作對(duì)象 // Statement 類(lèi)中 createStatement() 創(chuàng)建一個(gè) Statement 對(duì)象來(lái)將 SQL 語(yǔ)句發(fā)送到數(shù)據(jù)庫(kù)。 stmt = conn.createStatement(); // 4、執(zhí)行sql語(yǔ)句 // int executeUpdate(String sql) // 專(zhuān)門(mén)執(zhí)行DML語(yǔ)句 // 返回值是“影響數(shù)據(jù)庫(kù)中的記錄條數(shù)” int count = stmt.executeUpdate("update dept set dname = '銷(xiāo)售部',loc = '合肥' where deptno = 20;"); System.out.println(count == 1 ? "保存成功":"保存失敗"); // 5、處理查詢(xún)結(jié)果集 } catch(SQLException e) { e.printStackTrace(); } finally { // 6、釋放資源 // 從小到大依次關(guān)閉 //finally語(yǔ)句塊內(nèi)的語(yǔ)句一定會(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ù)庫(kù)操作對(duì)象 // 4、執(zhí)行sql語(yǔ)句 // 5、獲取查詢(xún)結(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語(yǔ)句 */ import java.sql.*; import java.util.*; public class JDBCTest05 { public static void main(String[] args) { // 1、注冊(cè)驅(qū)動(dòng) // 2、建立連接 // 3、獲取數(shù)據(jù)庫(kù)操作對(duì)象 // 4、執(zhí)行sql語(yǔ)句 // 5、獲取查詢(xún)結(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)化代碼的過(guò)程中,針對(duì)這六步
// 1、注冊(cè)驅(qū)動(dòng) // 2、獲取連接 // 3、獲取數(shù)據(jù)庫(kù)操作對(duì)象 // 4、執(zhí)行sql語(yǔ)句 // 5、獲取查詢(xún)結(jié)果集 // 6、釋放資源
第一步的注冊(cè)驅(qū)動(dòng)最終使用了反射,已達(dá)最優(yōu)
第二步的獲取連接已達(dá)最優(yōu),已經(jīng)有能力去完成JDBC連接數(shù)據(jù)庫(kù)的工具類(lèi)的封裝了
看到這里可以移步去學(xué)習(xí)—————>工具類(lèi)的封裝啦!
注:
第三步的獲取數(shù)據(jù)庫(kù)操作對(duì)象中我們是使用Statement接口
public interface Statement extends Wrapper, AutoCloseable
還可以?xún)?yōu)化成為PreparedStatement
public interface PreparedStatement extends Statement
在實(shí)際開(kāi)發(fā)過(guò)程中由于PreparedStatement能防止注入,且預(yù)先編譯SQL語(yǔ)句的特性使得程序健壯性提高,所以實(shí)際開(kāi)發(fā)中99.9%使用PreparedStatement。這是后話(huà),由于封裝工具類(lèi)主要封裝的是注冊(cè)驅(qū)動(dòng),獲取連接和釋放資源,后續(xù)將專(zhuān)門(mén)寫(xiě)一篇博客討論P(yáng)reparedStatement
此外在實(shí)際開(kāi)發(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通信),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10hibernate 配置數(shù)據(jù)庫(kù)方言的實(shí)現(xiàn)方法
這篇文章主要介紹了hibernate 配置數(shù)據(jù)庫(kù)方言的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05IntelliJ IDEA 編輯器的全局搜索中使用正則表達(dá)式的操作方法
這篇文章主要介紹了IntelliJ IDEA 編輯器的全局搜索中使用正則表達(dá)式的相關(guān)知識(shí),補(bǔ)充介紹了IDEA查找和替換實(shí)用正則,感興趣的朋友跟隨小編一起看看吧2024-01-01SpringMVC高級(jí)開(kāi)發(fā)功能實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringMVC高級(jí)開(kāi)發(fā)功能實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Spring和activiti進(jìn)行整合過(guò)程解析
這篇文章主要介紹了Spring和activiti進(jìn)行整合過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java如何通過(guò)枚舉實(shí)現(xiàn)有限狀態(tài)機(jī)
這篇文章主要介紹了Java如何通過(guò)枚舉實(shí)現(xiàn)有限狀態(tài)機(jī),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07