詳解Java基礎(chǔ)知識——JDBC
JDBC
Java DataBase Connectivity,java數(shù)據(jù)庫連接,為了降低操作數(shù)據(jù)的難度,java提供jdbc,按照java面向?qū)ο筇攸c(diǎn),對操作進(jìn)行了很多封裝。

JDBC提供了很多接口,然后不同數(shù)據(jù)庫廠商去實(shí)現(xiàn)這個(gè)接口,到底底層如何去實(shí)現(xiàn),不同的數(shù)據(jù)庫不一樣,不同的數(shù)據(jù)庫廠商需要提供接口實(shí)現(xiàn)類(驅(qū)動類、驅(qū)動程序 Driver、驅(qū)動)
我們連接不同的數(shù)據(jù)庫,我們只需要使用不同的驅(qū)動即可。
J:Java:提供訪問數(shù)據(jù)庫的規(guī)范(接口),
DBC:接口的實(shí)現(xiàn),廠商去實(shí)現(xiàn)這個(gè)接口。
JDBC是一種用于執(zhí)行SQL語句的java api.
版本號
1.1.1 Major. Minor. Build
Major:項(xiàng)目由架構(gòu)、大規(guī)模的變化
Minor:有新功能的時(shí)候
Build:編譯版本
JDBC開發(fā)
Java程序使用第三方提供工具框架,都需要導(dǎo)入jar包
可以通過以下網(wǎng)址搜索找到mysql的相關(guān)jar包
下載好jar包后,在于src同級的目錄下,建立一個(gè)lib文件夾,添加jar包,并添加依賴

代碼實(shí)現(xiàn)
通過一個(gè)簡單的案例來實(shí)現(xiàn)JDBC的使用
import java.sql.*;
public class Demo02 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1注冊驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
//2建立連接
String url = "jdbc:mysql://localhost:3306/mydb01";
String usernName = "xxx"; //登錄數(shù)據(jù)庫的賬號
String password = "xxxx"; //登錄數(shù)據(jù)庫的密碼
Connection conn = DriverManager.getConnection(url, usernName, password);
//3獲取執(zhí)行sQL語句的對象
Statement statement = conn.createStatement();
//4獲取數(shù)據(jù)庫返回的結(jié)果
String sql = "delete from emp where empno = " +"7499";
String sqlUpdate = "update emp set sal = "+10000+" where empno = " +"7369";
String sqlInsert = "INSERT INTO emp VALUES(2018,\"boss\",\"king\",NULL,\"2018-8-
8\",15000,10000,10);";
//5處理數(shù)據(jù)集
int i = statement.executeUpdate(sql);
int s = statement.executeUpdate(sqlUpdate);
int ins = statement.executeUpdate(sqlInsert);
System.out.println(i + "行受到影響----刪除");
System.out.println(s + "行受到影響----更新");
System.out.println(ins + "行受到影響----插入");
//6關(guān)閉連接
statement.close();
conn.close();
}
}
使用JDBC的順序
- (1)注冊數(shù)據(jù)庫驅(qū)動
- (2)和數(shù)據(jù)庫建立連接
- (3)獲取執(zhí)行SQL語句的對象
- (4)獲取數(shù)據(jù)庫返回的結(jié)果
- (5)處理數(shù)據(jù)集(邏輯代碼)
- (6)釋放資源,關(guān)閉連接
常用類
Connection
通過配置文件可以創(chuàng)建一個(gè)connect對象
Statement
- 通過connect對象獲取操作數(shù)據(jù)庫的Statement對象,
- 通過它來實(shí)現(xiàn)對數(shù)據(jù)庫增刪改查操作。
- executeQuery():查,返回?cái)?shù)據(jù)集
- executeUpdate():增刪改,返回int的數(shù)據(jù),影響的行數(shù)
ResultSet
數(shù)據(jù)集,可以理解就是一個(gè)集合。
取出數(shù)據(jù):
- 通過下標(biāo):從1開始
- 通過字段名:SQL語句中select后面跟的字段,有可能和數(shù)據(jù)庫一樣,也可能不一樣
JDBC的優(yōu)化
平時(shí)開發(fā)和項(xiàng)目上線之后使用的數(shù)據(jù)庫是不一樣的,不是同一個(gè)
這也就是我們說的,開發(fā)環(huán)境不一樣
開發(fā)環(huán)境不一樣,使用的數(shù)據(jù)庫也就不一樣,那么上面的數(shù)據(jù)庫中配置的三要素就要進(jìn)行修改
而這種修改是人工操作的,人工操作就有存在了失誤,而修改之后的.java文件,也要重新編譯,這也可能出現(xiàn)錯(cuò)誤
假設(shè)項(xiàng)目上線,需要以下四個(gè)步驟:
測試環(huán)境-->修改配置 -->重新編譯-->生產(chǎn)環(huán)境
如果想要避免上述出現(xiàn)的失誤的情況,就要繞開中間的兩個(gè)步驟
解決的方法就是,配置文件,添加配置文件,將要修改的配置信息存放到配置文件中,每次讀取信息從配置文件中讀取
而配置文件的位置是固定的,也不會重新編譯,這樣就可以降低風(fēng)險(xiǎn)
java中用IO流也可以讀取配置文件,通過一個(gè)專有的類Properties也可以讀寫配置文件
IO讀取配置文件
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class IoReadProp {
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {
//1注冊驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
String[] para = read();
//2建立連接
String url = para[0];
String usernName = para[1];
String password = para[2];
Connection conn = DriverManager.getConnection(url,usernName,password);
//3獲取執(zhí)行sQL語句的對象
Statement statement = conn.createStatement();
//4獲取數(shù)據(jù)庫返回的結(jié)果
String sql = "select * from emp";
ResultSet resultSet = statement.executeQuery(sql);
//5處理數(shù)據(jù)集
try {
while (resultSet.next()){
//.getXXX方法中的參數(shù) 1,字段名 2.字段的下標(biāo)
int empno = resultSet.getInt("empno");
String ename = resultSet.getString("ename");
String job = resultSet.getString(3);
Date date = resultSet.getDate(5);
System.out.println("empno:"+empno+", ename:"+ename+", job:"+job+", date:"+date);
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
//6關(guān)閉連接
resultSet.close();
statement.close();
conn.close();
}
}
public static String [] read()throws IOException {
FileReader fr = new FileReader( "E:\\javalearning\\src\\jdbc\\jdbc.properties" );
//創(chuàng)建 寫入 緩沖區(qū)
BufferedReader bufferedReader = new BufferedReader( fr );
String [] str = new String[3];
for(int i =0 ;i < 3;i++){
str[i] = bufferedReader.readLine().split("=")[1].replace(";","").trim();
}
bufferedReader.close();
fr.close();
return str;
}
}
Properties讀取配置文件
import java.io.*;
import java.sql.*;
import java.util.Iterator;
import java.util.Properties;
public class PropReadProp {
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {
//1注冊驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
//用戶數(shù)組存放數(shù)據(jù)庫信息
String[] para = new String[3];
//讀取配置文件
int i = 0;
Properties prop = new Properties();
FileInputStream fileInputStream = new FileInputStream("E:\\javalearning\\src\\jdbc\\jdbc.properties");
InputStream in = new BufferedInputStream(fileInputStream);
prop.load(in);
Iterator<String> it = prop.stringPropertyNames().iterator();
while (it.hasNext()) {
para[i] = prop.getProperty(it.next());
i++;
}
in.close();
//2建立連接
String url = para[0];
String usernName = para[1];
String password = para[2];
Connection conn = DriverManager.getConnection(url, usernName, password);
//3獲取執(zhí)行sQL語句的對象
Statement statement = conn.createStatement();
//4獲取數(shù)據(jù)庫返回的結(jié)果
String sql = "select * from emp";
ResultSet resultSet = statement.executeQuery(sql);
//5處理數(shù)據(jù)集
try {
while (resultSet.next()) {
//.getXXX方法中的參數(shù) 1,字段名 2.字段的下標(biāo)
int empno = resultSet.getInt("empno");
String ename = resultSet.getString("ename");
String job = resultSet.getString(3);
Date date = resultSet.getDate(5);
System.out.println("empno:" + empno + ", ename:" + ename + ", job:" + job + ", date:" + date);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//6關(guān)閉連接
resultSet.close();
statement.close();
conn.close();
}
}
}
分層DAO
Data Access Object數(shù)據(jù)訪問對象是一個(gè)面向?qū)ο蟮臄?shù)據(jù)庫接口
會建立一個(gè)包:dao,里面的類都是用來操作數(shù)據(jù)庫的。
通常情況下,有幾張表,就有幾個(gè)DAO
分層Entity、bean、pojo
實(shí)體,也就是一個(gè)一個(gè)類,該類里面只有屬性,和對應(yīng)set.get方法
往往一個(gè)表一個(gè)實(shí)體,實(shí)體的屬性和表的字段有沒有關(guān)系,名字一般一樣,類型相對應(yīng)
使用逆向工程,通過表導(dǎo)出實(shí)體。
Utils 工具類
代替我們?nèi)ゲ僮饕幌盗械倪B接關(guān)閉等操作
案例:
目錄結(jié)構(gòu)如下,

EmpDAO代碼如下:
package jdbc.dao;
import jdbc.entity.Emp;
import jdbc.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class EmpDAO {
/**
* 根據(jù)員工id獲取員工信息
*/
public Emp getEmpById(Integer id){
Connection connection =null;
Statement statement = null;
ResultSet rs = null;
Emp emp = null;
try {
connection = JDBCUtils.getConnection();
statement = connection.createStatement();
rs = statement.executeQuery("select * from emp where empno='"+id+"'");
while (rs.next()){
emp = new Emp();
int empno = rs.getInt("empno");
emp.setEmpno(empno);
String ename = rs.getString("ename");
emp.setEname(ename);
String job = rs.getString(3);
emp.setJob(job);
String hiredate = rs.getString(5);
emp.setHiredate(hiredate);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JDBCUtils.close(connection,statement,rs);
}
return emp;
}
public Emp getEmpById(String id){
Connection connection =null;
Statement statement = null;
ResultSet rs = null;
Emp emp = null;
try {
connection = JDBCUtils.getConnection();
statement = connection.createStatement();
rs = statement.executeQuery("select * from emp where empno="+id);
while (rs.next()){
emp = new Emp();
int empno = rs.getInt("empno");
emp.setEmpno(empno);
String ename = rs.getString("ename");
emp.setEname(ename);
String job = rs.getString(3);
emp.setJob(job);
String hiredate = rs.getString(5);
emp.setHiredate(hiredate);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JDBCUtils.close(connection,statement,rs);
}
return emp;
}
}
entity中的Emp代碼如下
package jdbc.entity;
public class Emp {
//emp表中的相關(guān)屬性
private Integer empno;
private String ename;
private String job;
private String mgr;
private String hiredate ;
private double sal;
private double comm;
private Integer deptno;
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getMgr() {
return mgr;
}
public void setMgr(String mgr) {
this.mgr = mgr;
}
public String getHiredate() {
return hiredate;
}
public void setHiredate(String hiredate) {
this.hiredate = hiredate;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
//默認(rèn)輸出方法
@Override
public String toString() {
return "Emp{" +
"empno=" + empno +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", mgr='" + mgr + '\'' +
", hiredate='" + hiredate + '\'' +
", sal=" + sal +
", comm=" + comm +
", deptno=" + deptno +
'}';
}
}
utils中的JDBCUtils代碼如下
package jdbc.utils;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Iterator;
import java.util.Properties;
public class JDBCUtils {
private static final String URL ;
private static final String USERNAME ;
private static final String PASSWORD ;
static{
String [] parp = null;
try {
parp = PropRead();
} catch (IOException e) {
e.printStackTrace();
}
URL = parp[0];
USERNAME = parp[1];
PASSWORD=parp[2];
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 創(chuàng)建連接
*/
public static Connection getConnection() throws SQLException {
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return conn;
}
public static void close(Connection co , Statement state, ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(state !=null){
try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(co !=null){
try {
co.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection co , Statement state){
if(state !=null){
try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(co !=null){
try {
co.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 讀取配置文件
* @return
* @throws IOException
*/
public static String [] PropRead()throws IOException {
String[] para = new String[3];
int i = 0;
Properties prop = new Properties();
FileInputStream fileInputStream = new FileInputStream("E:\\javalearning\\src\\jdbc\\jdbc.properties");
InputStream in = new BufferedInputStream(fileInputStream);
prop.load(in);
Iterator<String> it = prop.stringPropertyNames().iterator();
while (it.hasNext()) {
para[i] = prop.getProperty(it.next());
i++;
}
in.close();
return para;
}
}
測試代碼如下:
package jdbc;
import jdbc.dao.EmpDAO;
import jdbc.entity.Emp;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
EmpDAO empDAO = new EmpDAO();
System.out.println("請輸入ID");
Scanner scanner = new Scanner( System.in );
String value = scanner.nextLine();
Emp emp = empDAO.getEmpById (value);
Emp emp1 = empDAO.getEmpById (7900);
System.out.println(emp);
System.out.println(emp1);
}
}
這樣就簡單實(shí)現(xiàn)了一個(gè)分層的使用JDBC的案例
SQL注入攻擊
根據(jù)上述案例,我們可以輸入一個(gè)員工的id來查找該員工
但是有一個(gè)問題,你如何去規(guī)定用戶的輸入,下面給大家看一個(gè)現(xiàn)象

我的數(shù)據(jù)庫在中并沒有123456789這個(gè)id的人,那么為什么還會有結(jié)果呢?
就是因?yàn)槲覀兊膕ql語句是根據(jù)字符串拼接生成的,當(dāng)你輸入的數(shù)據(jù)中包含sql關(guān)鍵字時(shí),會被當(dāng)成sql語句去執(zhí)行
注意:這是很危險(xiǎn)的!
不友好的用戶可以根據(jù)這個(gè)漏洞對你的數(shù)據(jù)庫進(jìn)行修改,甚至刪除你的數(shù)據(jù)庫!
解決方法:PreparedStatement類
PreparedStatement是statement的子類
解決原理:
SQL語句不在拼接,而是通過預(yù)處理,也就是說,用戶輸入的任何內(nèi)容,都只能作為值,不解析特殊字符。
修改之后打代碼如下:
public Emp getEmpById2(String id){
Connection connection =null;
PreparedStatement statement = null;
ResultSet rs = null;
Emp emp = null;
try {
connection = JDBCUtils.getConnection();
String sql = "select * from emp where empno=?";
statement = connection.prepareStatement(sql);
statement.setString(1,id);
rs = statement.executeQuery();
while (rs.next()){
emp = new Emp();
int empno = rs.getInt("empno");
emp.setEmpno(empno);
String ename = rs.getString("ename");
emp.setEname(ename);
String job = rs.getString(3);
emp.setJob(job);
String hiredate = rs.getString(5);
emp.setHiredate(hiredate);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JDBCUtils.close(connection,statement,rs);
}
return emp;
}
再次測試:結(jié)果如圖

總結(jié):并不是意味著Statement不能用,或者不能SQL拼接
但是如果是前端穿過的來的值需要直接放到SQL語句中,就需要注意。
以上所述是小編給大家介紹的Java基礎(chǔ)知識——JDBC詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- Java中使用JDBC操作數(shù)據(jù)庫簡單實(shí)例
- Java使用JDBC連接數(shù)據(jù)庫的實(shí)現(xiàn)方法
- Java加載JDBC驅(qū)動程序?qū)嵗斀?/a>
- java使用jdbc連接數(shù)據(jù)庫工具類和jdbc連接mysql數(shù)據(jù)示例
- 基于Java回顧之JDBC的使用詳解
- java jdbc連接mysql數(shù)據(jù)庫實(shí)現(xiàn)增刪改查操作
- Java開發(fā)Oracle數(shù)據(jù)庫連接JDBC Thin Driver 的三種方法
- 在eclipse導(dǎo)入Java的jar包的方法JDBC(圖文說明)
- java中JDBC實(shí)現(xiàn)往MySQL插入百萬級數(shù)據(jù)的實(shí)例代碼
- JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫實(shí)例代碼
相關(guān)文章
MyBatis中多對一和一對多數(shù)據(jù)的處理方法
這篇文章主要介紹了MyBatis中多對一和一對多數(shù)據(jù)的處理,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
解決idea打包成功但是resource下的文件沒有成功的問題
這篇文章主要介紹了解決idea打包成功但是resource下的文件沒有成功的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Spring Security中用JWT退出登錄時(shí)遇到的坑
使用了JWT后,每次請求都要攜帶 Bearer Token 并且被專門的過濾器攔截解析之后才能將用戶認(rèn)證信息保存到 SecurityContext 中去,接下來通過本文給大家介紹Spring Security中用JWT退出登錄時(shí)遇到的坑,感興趣的朋友一起看看吧2021-10-10
微服務(wù)間調(diào)用Retrofit在Spring?Cloud?Alibaba中的使用
這篇文章主要為大家介紹了微服務(wù)間調(diào)用Retrofit在Spring?Cloud?Alibaba中的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng))
這篇文章主要介紹了SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
java使用HashMap實(shí)現(xiàn)斗地主(有序版)
這篇文章主要為大家詳細(xì)介紹了java使用ArrayList實(shí)現(xiàn)斗地主游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Java Speech API實(shí)現(xiàn)語音識別
Java語音識別是一項(xiàng)非常有用的功能,它可以將語音轉(zhuǎn)換為文本,從而實(shí)現(xiàn)語音輸入和語音控制功能,在當(dāng)今數(shù)字化時(shí)代,語音識別技術(shù)逐漸成為人機(jī)交互的重要方式之一,語音識別技術(shù)可以幫助我們將語音數(shù)據(jù)轉(zhuǎn)化為文字,進(jìn)而進(jìn)行后續(xù)的處理和分析2023-10-10

