Java使用JDBC連接數(shù)據(jù)庫的詳細步驟
一、JDBC是什么?
JDBC 指 Java 數(shù)據(jù)庫連接(Java Database Connectivity),是一種標(biāo)準(zhǔn)Java應(yīng)用編程接口( JAVA API),JDBC就是一套sun公司定義的接口,JDBC本質(zhì)上就是Sun公司制定的一套接口(interface)!每個數(shù)據(jù)庫廠商需要實現(xiàn)這套接口。我們只需要調(diào)用需要即可用來連接 Java 編程語言和廣泛的數(shù)據(jù)庫。
JDBC API 庫包含下面提到的每個任務(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ū)動程序來訪問數(shù)據(jù)庫,這樣可以方便的訪問數(shù)據(jù)。
JDBC 具有 ODBC 一樣的性能,允許 Java 程序包含與數(shù)據(jù)庫無關(guān)的代碼。
二、使用步驟
1.注冊驅(qū)動
數(shù)據(jù)庫廠商的Java程序員所寫的實現(xiàn)類 叫做驅(qū)動 Driver
注冊驅(qū)動
第一種注冊方法代碼如下:(不常用)
public class 注冊驅(qū)動 {
public static void main(String[] args) {
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}第二種方利用反射的特性,加載過程中注冊驅(qū)動的過程。
關(guān)于反射的補充: Java中的靈魂-反射機制
關(guān)于JDBC—MySQL中以類加載的方式注冊驅(qū)動(反射)詳解鏈接:
class.forName(com.mysql.jdbc.Driver);
上述一行代碼就可以通過反射這個動作調(diào)用類,實現(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";添加這個是為了防止亂碼,指定使用Unicode字符集 ,且使用UTF-8來編輯。
/*
url包括哪幾部分:
協(xié)議
IP
Port
資源名
eg:http://180.101.49.11:80/index.html
http:// 通信協(xié)議
180.101.49.11 IP地址
80 端口號
index.html 資源名
*/ // 2、獲取連接
/*
url包括哪幾部分:
協(xié)議
IP
Port
資源名
eg:http://180.101.49.11:80/index.html
http:// 通信協(xié)議
180.101.49.11 IP地址
80 端口號
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ù)庫連接對象 : " + conn); //數(shù)據(jù)庫連接對象com.mysql.jdbc.JDBC4Connection@1ae369b73.獲取數(shù)據(jù)庫操作對象
// 3、獲取數(shù)據(jù)庫操作對象
// Statement 類中 createStatement() 創(chuàng)建一個 Statement 對象來將 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é)果集對象,即使ResultSet的實例化對象!
6.釋放資源
finally {
// 6、釋放資源
// 從小到大依次關(guān)閉
//finally語句塊內(nèi)的語句一定會執(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)化:(比較兩種注冊驅(qū)動的方法)
import java.sql.*;
public class JDBCTest01 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;//先創(chuàng)建連接對象 和 操作對象 并且引用為空,是為了對象變量的生命周期不僅僅局限于try語句塊內(nèi),而是在整個main方法內(nèi),方便后續(xù)finally語句塊內(nèi)釋放資源
try{
// 1、注冊驅(qū)動
Driver driver = new com.mysql.jdbc.Driver(); //多態(tài),父類型引用指向子類型對象
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 端口號
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ù)庫連接對象 : " + conn); //數(shù)據(jù)庫連接對象com.mysql.jdbc.JDBC4Connection@1ae369b7
// 3、獲取數(shù)據(jù)庫操作對象
// Statement 類中 createStatement() 創(chuàng)建一個 Statement 對象來將 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)的語句一定會執(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)化:(比較兩種注冊驅(qū)動的方法)
package com.zdx.source.code.jdbc;
/*
JDBC完成Delete
*/
import java.sql.*;
public class JDBCTest02 {
public static void main(String[] args) {
// 1、注冊驅(qū)動
// 2、獲取連接
// 3、獲取數(shù)據(jù)庫操作對象
// 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)化:(最佳注冊驅(qū)動獲取連接)
package com.zdx.source.code.jdbc;
/*
注冊驅(qū)動的另一種方式
*/
import java.sql.*;
public class JDBCTest03 {
public static void main(String[] args) {
try{
// 注冊驅(qū)動
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)化:(對操作結(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、注冊驅(qū)動
// 2、建立連接
// 3、獲取數(shù)據(jù)庫操作對象
// 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)化代碼的過程中,針對這六步
// 1、注冊驅(qū)動
// 2、獲取連接
// 3、獲取數(shù)據(jù)庫操作對象
// 4、執(zhí)行sql語句
// 5、獲取查詢結(jié)果集
// 6、釋放資源第一步的注冊驅(qū)動最終使用了反射,已達最優(yōu)
第二步的獲取連接已達最優(yōu),已經(jīng)有能力去完成JDBC連接數(shù)據(jù)庫的工具類的封裝了
看到這里可以移步去學(xué)習(xí)—————>工具類的封裝啦!
注:
第三步的獲取數(shù)據(jù)庫操作對象中我們是使用Statement接口
public interface Statement extends Wrapper, AutoCloseable
還可以優(yōu)化成為PreparedStatement
public interface PreparedStatement extends Statement
在實際開發(fā)過程中由于PreparedStatement能防止注入,且預(yù)先編譯SQL語句的特性使得程序健壯性提高,所以實際開發(fā)中99.9%使用PreparedStatement。這是后話,由于封裝工具類主要封裝的是注冊驅(qū)動,獲取連接和釋放資源,后續(xù)將專門寫一篇博客討論PreparedStatement
此外在實際開發(fā)中除了掌握上述六步還需要掌握事務(wù)提交回滾三部曲。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java實現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信)
這篇文章主要介紹了java實現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
hibernate 配置數(shù)據(jù)庫方言的實現(xiàn)方法
這篇文章主要介紹了hibernate 配置數(shù)據(jù)庫方言的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
IntelliJ IDEA 編輯器的全局搜索中使用正則表達式的操作方法
這篇文章主要介紹了IntelliJ IDEA 編輯器的全局搜索中使用正則表達式的相關(guān)知識,補充介紹了IDEA查找和替換實用正則,感興趣的朋友跟隨小編一起看看吧2024-01-01
SpringMVC高級開發(fā)功能實現(xiàn)過程解析
這篇文章主要介紹了SpringMVC高級開發(fā)功能實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06

