Java基礎(chǔ)之JDBC的數(shù)據(jù)庫連接與基本操作
一、JDBC概述
- JDBC全稱Java Database Connectivity,它是一個(gè)獨(dú)立于特定數(shù)據(jù)庫管理系統(tǒng)、通用的SQL數(shù)據(jù)庫存取和操作的公共接口,定義了用來訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)Java類庫,使用這個(gè)類庫可以以一種標(biāo)準(zhǔn)的方法、方便地訪問數(shù)據(jù)庫資源
- 通俗的來說,JDBC就是讓我們通過Java來連接任何提供了JDBC驅(qū)動程序的數(shù)據(jù)庫系統(tǒng),比如我有一個(gè)SQLServer數(shù)據(jù)和一個(gè)Mysql數(shù)據(jù)庫,我可以通過Java的JDBC來完成前面學(xué)習(xí)SQL中的所有操作,而無需在命令行來分別連接它們兩個(gè),就像這樣
二、JDBC操作數(shù)據(jù)庫、操作表步驟
我來總結(jié)一下JDBC操作數(shù)據(jù)庫與表的步驟,然后詳細(xì)來介紹它們
1.注冊驅(qū)動 (只做一次)
2.建立連接(Connection)
3.創(chuàng)建執(zhí)行SQL的語句(Statement)
4.執(zhí)行語句
5.處理執(zhí)行結(jié)果(ResultSet)
6.釋放資源
看到這里是不是很熟悉,沒錯(cuò),就跟我們前面學(xué)習(xí)Mysql一樣,首先我來介紹一下JDBC的結(jié)構(gòu)與數(shù)據(jù)庫的連接
三、JDBC體系結(jié)構(gòu)與JDBC API
JDBC體系結(jié)構(gòu)由下面兩部分組成:
- 面向應(yīng)用的API:Java API,抽象接口,供應(yīng)用程序開發(fā)人員使用(連接數(shù)據(jù)庫,執(zhí)行SQL語句,獲得結(jié)果)。
- 面向數(shù)據(jù)庫的API:Java Driver API,供開發(fā)商開發(fā)數(shù)據(jù)庫驅(qū)動程序使用
JDBC API
- JDBC API 是一系列的接口,它使得應(yīng)用程序能夠進(jìn)行數(shù)據(jù)庫聯(lián)接,執(zhí)行SQL語句,并且得到返回結(jié)果
四、注冊與加載驅(qū)動
Driver接口
- java.sql.Driver 接口是所有 JDBC 驅(qū)動程序需要實(shí)現(xiàn)的接口。這個(gè)接口是提供給數(shù)據(jù)庫廠商使用的,不同數(shù)據(jù)庫廠商提供不同的實(shí)現(xiàn)
- 在程序中不需要直接去訪問實(shí)現(xiàn)了 Driver 接口的類,而是由驅(qū)動程序管理器類(java.sql.DriverManager)去調(diào)用這些Driver實(shí)現(xiàn)
- Oracle的驅(qū)動:oracle.jdbc.driver.OracleDriver
- mySql的驅(qū)動: com.mysql.jdbc.Driver
加載與注冊JDBC驅(qū)動
前面我們說了,JDBC就是通過一個(gè)接口和不同數(shù)據(jù)庫提供了JDBC的驅(qū)動來完成數(shù)據(jù)的操作,因此,我們將驅(qū)動加載到JDBC中,加載驅(qū)動有兩種方式:
方式一:加載 JDBC 驅(qū)動需調(diào)用 Class 類的靜態(tài)方法 forName(),向其傳遞要加載的 JDBC 驅(qū)動的類名
Class.forName(“com.mysql.jdbc.Driver”);
方式二:DriverManager 類是驅(qū)動程序管理器類,負(fù)責(zé)管理驅(qū)動程序
DriverManager.registerDriver(com.mysql.jdbc.Driver);
通常不用顯式調(diào)用 DriverManager 類的 registerDriver() 方法來注冊驅(qū)動程序類的實(shí)例,因?yàn)?Driver 接口的驅(qū)動程序類都包含了靜態(tài)代碼塊,在這個(gè)靜態(tài)代碼塊中,會調(diào)用 DriverManager.registerDriver() 方法來注冊自身的一個(gè)實(shí)例
五、建立連接(Connection)
- 當(dāng)我們注冊并加載驅(qū)動后,就可以連接數(shù)據(jù)庫了,方法和前面我們學(xué)習(xí)Mysql一樣,首先需要輸入賬號,密碼等信息
- 在JDBC中,我們需要調(diào)用DriverManager 類的 getConnection() 方法建立到數(shù)據(jù)庫的連接
- user,password可以用“屬性名=屬性值”方式告訴數(shù)據(jù)庫;
- 在JDBC中連接數(shù)據(jù)庫需要一個(gè)特殊的屬性,JDBC URL,它用于連接我們需要操作的數(shù)據(jù)庫
- JDBC URL的標(biāo)準(zhǔn)由三部分組成,各部分間用冒號分隔。
jdbc:子協(xié)議:子名稱 協(xié)議:JDBC URL中的協(xié)議總是jdbc 子協(xié)議:子協(xié)議用于標(biāo)識一個(gè)數(shù)據(jù)庫驅(qū)動程序 子名稱:一種標(biāo)識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化,用子名稱的目的是為了定位數(shù)據(jù)庫提供足夠的信息。包含主機(jī)名(對應(yīng)服務(wù)端的ip地址),端口號,數(shù)據(jù)庫名
下面我來列舉幾個(gè)常見的JDBC URL,大家使用的時(shí)候直接復(fù)制就好
// 對于 Oracle 數(shù)據(jù)庫連接,采用如下形式: jdbc:oracle:thin:@localhost:1521:DatabaseName // 對于 SQLServer 數(shù)據(jù)庫連接,采用如下形式: jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid // 對于 MYSQL 數(shù)據(jù)庫連接,采用如下形式: jdbc:mysql://localhost:3306/DatabaseName // 插入中文的時(shí)候,這個(gè)url要寫成這個(gè) jdbc:mysql://localhost:3306/數(shù)據(jù)庫名稱?useUnicode=true&characterEncoding=UTF-8
小伙伴們注意一下,當(dāng)我們使用Java向數(shù)據(jù)庫中插入一個(gè)數(shù)據(jù)時(shí),如果是中文,首先數(shù)據(jù)庫和表的編碼是utf8,其次就是我們要在URL中聲明一下編碼是UTF-8,不然插入數(shù)據(jù)是?,如果你們遇到這個(gè)問題,那就忽略它
好了,下面是連接數(shù)據(jù)庫的示例代碼,這里我操作的是Mysql數(shù)據(jù)庫
package com.company;
// 導(dǎo)入依賴包
import org.junit.Test;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class Demo1 {
/*
*獲取connect的三種方式
* */
public static void main(String[] args) {
System.out.println("JDBC Test...");
}
// 使用Driver來實(shí)現(xiàn)數(shù)據(jù)庫連接
@Test
public void test1() throws SQLException {
//
Driver driver=new com.mysql.jdbc.Driver();
Properties p1 = new Properties();
p1.setProperty("user", "root");
p1.setProperty("password", "mysql123");
Connection connect = driver.connect("jdbc:mysql://localhost:3306/myemployees", p1);
System.out.println("connect = " + connect);
}
// 使用DriverManager來實(shí)現(xiàn)數(shù)據(jù)庫連接
@Test
public void test2() throws SQLException {
com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
Properties p1 = new Properties();
p1.setProperty("user", "root");
p1.setProperty("password", "mysql123");
DriverManager.registerDriver(driver);
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/myemployees", p1);
System.out.println("connection = " + connection);
}
// 將賬號密碼抽出到配置文件中,并使用IO流讀取配置文件的方式連接數(shù)據(jù)庫
@Test
public void test3() throws Exception {
Properties p = new Properties();
FileInputStream fis = new FileInputStream("p.properties");
p.load(fis);
fis.close();
Class.forName(p.getProperty("driverClass"));
Connection connection = DriverManager.getConnection(p.getProperty("url"),
p.getProperty("user"), p.getProperty("password"));
System.out.println("connection = " + connection);
}
}
properties文件內(nèi)容
url=jdbc:mysql://localhost:3306/myemployees user=root password=mysql123 driverClass=com.mysql.jdbc.Driver
六、使用PreparedStatement
介紹完注冊驅(qū)動與數(shù)據(jù)庫的連接,接下來就是操作SQL了,在JDBC中,操作SQL需要使用Connection 對象的 preparedStatement() 方法獲取 PreparedStatement 對象
PreparedStatement 接口是 Statement 的子接口,它表示一條預(yù)編譯過的 SQL 語句
PreparedStatement 對象所代表的 SQL 語句中的參數(shù)用問號(?)來表示,調(diào)用 PreparedStatement 對象的 setXxx() 方法來設(shè)置這些參數(shù). setXxx() 方法有兩個(gè)參數(shù),第一個(gè)參數(shù)是要設(shè)置的 SQL 語句中的參數(shù)的索引(從 1 開始),第二個(gè)是設(shè)置的 SQL 語句中的參數(shù)的值
在操作SQL前還要說明一下數(shù)據(jù)類型,我們知道SQL與Java的數(shù)據(jù)類型命名是不一樣的,所以我們在編碼時(shí)要注意
| java類型 | SQL類型 |
| boolean | BIT |
| byte | TINYINT |
| short | SMALLINT |
| int | INTEGER |
| long | BIGINT |
| String | CHAR,VARCHAR,LONGVARCHAR |
| byte array | BINARY , VAR BINARY |
| java.sql.Date | DATE |
| java.sql.Time | TIME |
| java.sql.Timestamp | TIMESTAMP |
使用PreparedStatementSQL的操作步驟
1.調(diào)用連接對象的prepareStatement方法,創(chuàng)建PreparedStatement對象
2.完成預(yù)編譯的SQL語句
3.對SQL語句中的占位符進(jìn)行賦值
4.提交SQL語句
5.釋放資源
接下來就是操作SQL增刪改查的示例代碼(為了方便操作,我將數(shù)據(jù)庫連接抽出到了JDBCUtils類中)
// 使用PreparedStatement來完成數(shù)據(jù)的增刪改查操作
package com.company.jdbc;
import org.junit.Test;
import java.io.FileInputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/*
對數(shù)據(jù)庫進(jìn)行增,刪,改,查的操作
*/
public class CRUDDemo {
/*
添加一條數(shù)據(jù)
CREATE TABLE student(
sid INT,
sname VARCHAR(20),
sage INT
)
*/
@Test
public void test() throws SQLException {
//1.獲取數(shù)據(jù)庫連接對象
Connection connection = JDBCUtils.getConnection();
//2.預(yù)編譯
// ? : 占位符(只能是設(shè)置數(shù)據(jù)的地方可以寫成占位符)
String sql = "insert into student(sid,sname,sage) values(?,?,?)";
PreparedStatement ps = connection.prepareStatement(sql);
//3.給占位符賦值
/*
setInt(int parameterIndex, int x)
parameterIndex : 參數(shù)索引(第幾個(gè)占位符)
x : 數(shù)據(jù)
*/
ps.setInt(1,100);
//數(shù)據(jù)設(shè)置成中文可不可以取決于表的編碼集
ps.setString(2,"longge");
ps.setInt(3,20);
//4.執(zhí)行sql
//返回值 : 有幾條數(shù)據(jù)受到影響
int result = ps.executeUpdate();//增,刪,改的語句使用該方法
System.out.println("有"+result+"條數(shù)據(jù)受到影響");
//5.關(guān)資源
JDBCUtils.close(ps,connection);
}
/*
改
*/
@Test
public void test2() throws SQLException {
//1.獲取數(shù)據(jù)庫連接對象
Connection connection = JDBCUtils.getConnection();
//2.預(yù)編譯
String sql = "update student set sid=? where sid=?";
PreparedStatement ps = connection.prepareStatement(sql);
//3.給占位符賦值
ps.setInt(1,10);
ps.setInt(2,100);
//4.執(zhí)行sql語句
int result = ps.executeUpdate();
System.out.println("有"+result+"條數(shù)據(jù)受到影響");
//5.關(guān)閉資源
JDBCUtils.close(ps,connection);
}
/*
刪除數(shù)據(jù)
*/
@Test
public void test3() throws SQLException {
//1.獲取數(shù)據(jù)庫連接對象
Connection connection = JDBCUtils.getConnection();
//2.預(yù)編譯
String sql = "delete from student where sid=?";
PreparedStatement ps = connection.prepareStatement(sql);
//3.給占位符賦值
ps.setInt(1,10);
//4.執(zhí)行sql語句
int i = ps.executeUpdate();
System.out.println("有"+i+"條數(shù)據(jù)受到影響");
//5.關(guān)閉資源
JDBCUtils.close(ps,connection);
}
/*
查詢數(shù)據(jù)
*/
@Test
public void test4() throws Exception {
List<Student> students = getStudent();
for (Student s : students) {
System.out.println(s);
}
}
public List<Student> getStudent() throws Exception {
//1.獲取數(shù)據(jù)庫連接對象
Connection connection = JDBCUtils.getConnection();
//2.預(yù)編譯
PreparedStatement ps = connection.prepareStatement("select sid,sname,sage from student");
//3.執(zhí)行sql語句
ResultSet resultSet = ps.executeQuery();//查詢語必須執(zhí)行此方法
List<Student> list = new ArrayList<>();
//4.遍歷ResultSet
while(resultSet.next()){//是否有數(shù)據(jù)
/*
getInt(String columnLabel) :根據(jù)字段名獲取對應(yīng)的數(shù)據(jù)
getInt(int columnIndex) : 根據(jù)列的索引獲取對應(yīng)的數(shù)據(jù)
*/
int sid = resultSet.getInt("sid");
String sname = resultSet.getString("sname");
int sage = resultSet.getInt("sage");
//System.out.println(sid + " " + sname + " " + sage);
list.add(new Student(sid,sname,sage));
}
//5.關(guān)閉資源
JDBCUtils.close(ps,connection,resultSet);
return list;
}
}
JDBCUtils連接數(shù)據(jù)庫的工具類
//JDBCUtils類,專門實(shí)現(xiàn)數(shù)據(jù)庫的連接與資源釋放操作
package com.company.jdbc;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String driverClass;
private static String url;
private static String username;
private static String password;
static{
FileInputStream fis = null;
try {
//1.獲取數(shù)據(jù)庫連接對象
//通過Properties讀取內(nèi)容
//1.創(chuàng)建Properties對象
Properties p = new Properties();
//2.加載流
fis = new FileInputStream("jdbc.properties");
p.load(fis);
driverClass = p.getProperty("driverClass");
url = p.getProperty("url");
username = p.getProperty("username");
password = p.getProperty("password");
}catch (Exception e){
//終止程序的運(yùn)行
e.printStackTrace();
//將編譯時(shí)異常轉(zhuǎn)換成運(yùn)行時(shí)異常
throw new RuntimeException("xxxxxxxx");
}finally {
if (fis != null){
//3.關(guān)資源
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
獲取連接對象
*/
public static Connection getConnection(){
try {
Class.forName(driverClass);
//獲取數(shù)據(jù)庫連接對象
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("獲取連接失敗");
}
}
/*
關(guān)閉資源
*/
public static void close(PreparedStatement ps, Connection connection) {
if (ps != null){
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(PreparedStatement ps, Connection connection, ResultSet resultSet) {
close(ps,connection);
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
七、關(guān)于ResultSet的說明
在前面對數(shù)據(jù)的增刪改查操作中,查詢操作比較復(fù)雜一些,因?yàn)槲覀円邮諗?shù)據(jù)庫返回的結(jié)果,因此我們要了解一下ResultSet 接口,它由數(shù)據(jù)庫廠商實(shí)現(xiàn)
查詢需要調(diào)用Prepared Statement 的 executeQuery() 方法,查詢結(jié)果是一個(gè) ResultSet 對象
ResultSet 對象維護(hù)了一個(gè)指向當(dāng)前數(shù)據(jù)行的游標(biāo),初始的時(shí)候,游標(biāo)在第一行之前,可以通過 ResultSet 對象的 next() 方法移動到下一行,具體方法可以自定百度
ResultSet:代表結(jié)果集,其封裝了使用 JDBC 進(jìn)行查詢的結(jié)果. 調(diào)用 PreparedStatement 對象的 executeQuery() 可以得到結(jié)果集.ResultSet 返回的實(shí)際上就是一張數(shù)據(jù)表. 有一個(gè)指針指向數(shù)據(jù)表的第一條記錄的前面
八、總結(jié)
本章主要介紹了JDBC以及JDBC如何連接數(shù)據(jù)庫,實(shí)現(xiàn)數(shù)據(jù)的增刪改查操作,下一章是JDBC的擴(kuò)展知識—>我們自己實(shí)現(xiàn)的那個(gè)連接數(shù)據(jù)庫的工具類畢竟不是那么嚴(yán)謹(jǐn),下一章就是介紹一個(gè)框架,以后連接數(shù)據(jù)庫就不用這么麻煩了.
到此這篇關(guān)于Java基礎(chǔ)之JDBC的數(shù)據(jù)庫連接與基本操作的文章就介紹到這了,更多相關(guān)JDBC的數(shù)據(jù)庫連接與基本操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Hibernate中實(shí)現(xiàn)增刪改查的步驟詳解
本篇文章主要介紹了Hibernate中實(shí)現(xiàn)增刪改查的步驟與方法,具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02
Java實(shí)現(xiàn)JSP在Servelt中連接Oracle數(shù)據(jù)庫的方法
這篇文章主要介紹了Java實(shí)現(xiàn)JSP在Servelt中連接Oracle數(shù)據(jù)庫的方法,需要的朋友可以參考下2014-07-07
解決springboot項(xiàng)目找不到resources目錄下的資源問題
這篇文章主要介紹了解決springboot項(xiàng)目找不到resources目錄下的資源問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
springcloud config配置讀取優(yōu)先級過程詳解
這篇文章主要介紹了springcloud config配置讀取優(yōu)先級過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Spring Boot整合MyBatis連接Oracle數(shù)據(jù)庫的步驟全紀(jì)錄
這篇文章主要給大家介紹了關(guān)于Spring Boot整合MyBatis連接Oracle數(shù)據(jù)庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07

