前言
hello我是bigsai,今天我們們進行JDBC+MySQL實戰,非常適合初入門的小夥伴開啟新的世界。實現一個增刪改查(curd)的例子。先點贊再觀看、帥哥靚女養成好習慣!
在這個案例進行之前,你要確保自己電腦上擁有MySQL和IDEA編譯器,另外還要安裝MySQL資料庫連線管理工具Navicat。方能進行以下的操作。
如果以前沒見過或者使用過也不要緊,本課程提供傻瓜式教學你只需跟著我的要求來包成功包會。
通過本翩你可以掌握以下內容:
- MySQL資料庫的建立
- JDBC+MySQL專案的建立
- JDBC成功對MySQL增刪改查
案例分析
本次案例到底是個什麼結果呢?本案例實現一個學生資訊的管理,即學生個人資訊的增刪改查。
核心思路拆解
我們該如何設計這個專案呢?
別急別急,聽我慢慢說道。對於本案例的實戰,旨在實現用Java語言(JDBC)操作MySQL,核心的主軸是MySQL的資料,所以我們從MySQL為起始點入手,整個案例實現的流程大致可以分為:
- 分析設計需求、建立MySQL資料庫和表
- 建立Java專案,新增JDBC以及Junit單元測試的依賴
- 編寫專案程式碼,實現JDBC增刪改查案例
- 單元測試
而對於JDBC程式設計來說,它需要與MySQL進行連線互動,它也有一定流程順序需要遵守,通常為以下6個流程:
- 1:註冊驅動 (僅僅做一次)
- 2:建立連線(Connection)
- 3:建立執行SQL的語句(Statement)
- 4:執行語句
- 5:處理執行結果(ResultSet)
- 6:釋放資源
案例涉及知識點
本案例主要涉及的知識點為MySQL和JDBC。而這兩個知識點是Java Web開發非常常用的技術,下面我就給你介紹一番。
MySQL :
MySQL是當前非常流行的資料庫之一,且免費開源,資料庫是用來儲存資料的,就資料格式而言,有關係型資料和非關係型資料,MySQL是一種關係型資料庫。就web方面,MySQL是最好的RDBMS(關聯式資料庫管理系統:Relational Database Management System)之一:MySQL的sql語句是常用關聯式資料庫的標準之一,具有速度快、體積小、成本低等優勢,是中小企業以及學習使用的最好方式之一。
在Java中利用JDBC可以快速在應用中使用MySQL。除了DDL(資料庫模式定義語言:Data Definition Language)和DML(資料操縱語言:Data Manipulation Language)等傳統操作外,你可以通過JDBC使用MySQL的大部分功能。並且MySQL提供索引優化查詢速度,利用B+樹或雜湊方式的索引滿足不同場景查詢效能的要求。還提供檢視、函式、約束、觸發器等功能能夠使得資料庫滿足更多的場景使用。而MySQL提供的事務、回滾等機制能夠使得資料在安全性一致性方面有更大的保證。
JDBC
Java資料庫連線,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面(位於jdk的java.sql中)。我們通常說的JDBC是面向關係型資料庫的,提供了諸如查詢、更新、刪除、增加資料庫中資料的方法。在使用時候需要匯入具體的jar包,不同資料庫需要匯入的jar包不同。
而JDBC主要有以下API:
- DriverManager:負責載入不同驅動程式(Driver),並根據不同的請求,向呼叫者返回相應的資料庫連線(Connection)。
- Driver:驅動程式,會將自身載入到DriverManager中去,並處理相應的請求並返回相應的資料庫連線(Connection)。
- Connection:資料庫連線,負責與資料庫進行通訊,SQL執行以及事務處理都是在某個特定Connection環境中進行的。可以產生用以執行SQL的Statement、PreparedStatement等。
- Statement:用以執行SQL查詢和更新(針對靜態SQL語句和單次執行)。
- PreparedStatement:用以執行包含動態引數的SQL查詢和更新(在伺服器端編譯,允許重複執行以提高效率)繼承Statement,本案例使用PreparedStatement。
- CallableStatement:用以呼叫資料庫中的儲存過程。
- SQLException:代表在資料庫連線的建立和關閉和SQL語句的執行過程中發生了例外情況(即錯誤)。
我想現在你對MySQL和JDBC有了更清楚的認識吧,MySQL它就是一個資料庫供我們使用,而JDBC就是Java使用MySQL的一個工具和橋樑,結合上面知識,下面我們就開始實戰吧!
第一關 建立資料庫和專案
在實戰之前,需要把資料庫和專案建立好才能進行JDBC的增刪改查。
建立資料庫
我們使用Navicat建立資料庫,你可能好奇Navicat到底是個什麼樣的工具,有何作用?
其實Navicat是一個資料庫管理工具,它並不能直接修改MySQL的資料和結構,而是經過你的視覺化介面操作它幫你執行sql程式碼,因為考慮到如果直接讓你用sql運算元據庫,可能不太直觀並且上手難度挺大的,通過Navicat管理資料庫可以清晰看到資料庫結構、資料、設定情況也能夠很容易的進行更改,大大提升開發效率一定程度減少錯誤。可以參考下圖:
開啟Navicat連線資料庫,連線成功的資料庫右擊建立資料庫,資料庫名稱為:boxuegu
,字符集和排序規則使用其預設即可。
然後開啟boxuegu資料庫,在表的欄目右擊新建表,設定id,name,age,high四個欄位,其中id設為主鍵且自增。
儲存時候把這張表命名為student,代指學生表。這樣,學生表就新增完成了。其中id為自增主鍵,插入的時候不插入id會自動遞增插入,name就是學生的姓名,age表示學生年齡。high表示學生身高,我們用這幾個欄位表示一個學生資訊情況。
當然,如果你不喜歡使用資料庫管理工具進行這樣操作,更喜歡控制檯或者命令列建立資料庫以及表格,當然也是可以的:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for students
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
`high` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這樣我們資料庫以及表就建立完成啦,我們下面就要用JDBC對MySQL的這張表進行增刪改查實戰。讓你動手運算元據。
建立專案
我們建立java專案要引入JDBC的依賴,這裡我為了更簡單不讓你去自己找JDBC的jar包,使用Maven的方式引入jar包,所以我們使用IDEA建立Maven專案。
首先開啟IDEA,建立Maven專案,點選next。
接著填寫GroupId和ArtifactId可以自行填寫,本案例填寫com和JDBCTest,點選next。
緊接著選擇磁碟中一個資料夾作為專案的路徑,點選finish專案即建立成功。接著我們需要新增MySQL的JDBC依賴以及Junit單元測試依賴,在專案pom.xml檔案中新增以下內容:
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
然後專案就成功建立啦,緊接著建立以下類:
- main的java目錄下:sqlmanage類,用於編寫sql相關語句
- main的java目錄下:student類,表示student實體與MySQL的student
- test的java目錄下:test類,用於編寫單元測試。
有了JDBC的環境只需編寫正確的程式碼即可執行!對於專案最終的目錄是這樣的:
第二關 JDBC插入和查詢
我們上面有講過進行JDBC操作的6個步驟,但有些步驟不需要重複進行,比如載入驅動、建立連線、關閉等可以複用。此外,我們在專案中將MySQL中的資料和Java中的物件進行對映(即MySQL表中每一條記錄可以生成一個Java物件),專案中函式的設計基於Java物件而非MySQL中資料欄位,降低專案中各模組的耦合性。
預備工作
首先在student 類中編寫以下內容,該類與MySQL資料庫的student表對應。
public class student {
private int id;//與student表得id對應
private String name;//與student表得name對應
private int age;//年齡與student表得age對應
private int high;//身高與student表high對應
//帶id構造方法(查詢時使用)
public student(int id, String name, int age, int high) {
this.id = id;
this.name = name;
this.age = age;
this.high = high;
}
//不帶id得構造方法(插入時候使用)
public student(String name, int age, int high) {
this.name = name;
this.age = age;
this.high = high;
}
//toString()方法,控制檯列印測試使用
@Override
public String toString() {
return "student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", high=" + high +
"}\n";
}
//get set 方法,設定值,取值使用
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
}
緊接著處理sqlmanage類,我們將JDBC的一些操作封裝到這裡面。在初始化函式中進行註冊驅動、建立連線的操作。在sqlmanage中編寫以下內容:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class sqlmanage {
private Connection con=null;//資料庫連線,從DriverManager的方法獲得,用以產生執行sql的PreparedStatement
public sqlmanage() throws SQLException, ClassNotFoundException {
//step1 載入資料庫驅動
Class.forName("com.mysql.jdbc.Driver");
System.out.println("資料庫驅動載入成功");
//step2 連線資料庫
this.con = DriverManager.getConnection("jdbc:mysql://localhost:3306/boxuegu?useSSL=false","root","bigsai66");
System.out.println("資料庫連線成功");
}
public void close() throws SQLException {
this.con.close();;
}
}
其中通過Connection建立連線,Connection是一個介面類。其功能是與資料庫進行連線(會話)。建立Connection介面類物件:
Connection conn =DriverManager.getConnection(url, user, password)
;
其中url的格式要求為:
jdbc:mysql://<host>:<port>/<database_name>?property1=value1&property2=value2…
- host為主機地址或者域名,本地可以用localhost或127.0.0.1.
- database_name為MySQL中建立資料庫名,本案例中資料庫名為boxuegu。
- property用來配置一些例如編碼、時區等屬性。
其中user為MySQL登入使用者名稱,password為MySQL登入密碼。
單個插入
MySQL插入的sql語句很簡單:
insert into 表名
( 欄位1, 欄位2,...欄位n)
value
( 值1, 值2,...值n );
我們JDBC中進行插入操作使用的sql滿足上述規範,在sqlmanage中編寫insertStudent(student student)函式用來插入單個學生記錄,具體函式如下:
public void insertStudent(student student) throws SQLException {
//建立sql語句
String sql="insert into student(name,age,high)value(?,?,?)";
//PreparedStatement能夠對SQL語句進行預編譯,這樣防止了 SQL隱碼攻擊 提高了安全性。
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1,student.getName());
ps.setInt(2,student.getAge());
ps.setInt(3,student.getHigh());
//執行 sql 因為這裡插入操作就不對結處理
ps.executeUpdate();
ps.close();
}
在test類中的編寫insertTest()函式,用來測試插入三條學生的記錄:
@Test
public void insertTest() throws SQLException, ClassNotFoundException {
sqlmanage sqlmanage=new sqlmanage();
sqlmanage.insertStudent(new student("bigsai",22,180));
sqlmanage.insertStudent(new student("bigpian",21,165));
sqlmanage.insertStudent(new student("doudou",20,160));
}
執行完畢重新整理navicat中student表你會發現資料被成功插入了:
批量插入
如果同時有100組資料或者更多若干組資料讓你插入你會怎麼操作?
-
迴圈一個一個的插入
-
批處理一次插入多個
批量處理相比迴圈的單個單個處理起來省了很多時間,提高了系統效率。所以當遇到較多資料時可以選擇多個插入。
批量插入實現也很容易,在sqlmanage中編寫insertStudents(student students[])函式用來批量插入學生記錄:
public void insertStudents(student students[]) throws SQLException {
this.con.setAutoCommit(false);//不自動提交
String sql="insert into student(name,age,high)value(?,?,?)";
PreparedStatement ps =con.prepareStatement(sql);
for(int i=0;i<students.length;i++)
{
ps.setString(1,students[i].getName());
ps.setInt(2,students[i].getAge());
ps.setInt(3,students[i].getHigh());
ps.addBatch();
if(i%1000==0)
{
ps.executeBatch();
}
}
ps.executeBatch();
con.commit();
ps.close();
}
其中:
- con.setAutoCommit(false)意為不自動提交,因為我們在批量處理的時候一般手動提交提高效率。
- 主要通過PreparedStatement物件的addBatch()進行多組插入而未提交。
- 如果為設定不自動提交當執行executeBatch()時就會提交,但為了減小提交次數已經設定不自動提交。當且僅當con.commit()執行才會真的提交到MySQL中。
接著在test單元測試中編寫insertStudentsTest()函式進行測試批量插入:
@Test
public void insertStudentsTest() throws SQLException, ClassNotFoundException {
sqlmanage sqlmanage=new sqlmanage();
student students[]=new student[5];
for(int i=0;i<students.length;i++)
{
students[i]=new student("路人"+i,12,156);
}
sqlmanage.insertStudents(students);
}
執行完畢後你可以看到資料被成功插入MySQL中:
查詢資料
查詢的使用頻率要遠比其他的操作多,雖然有些複雜表的查詢可能會讓人比較頭疼,但基礎的sql查詢還是比較簡單,其語法格式為:
select 欄位1,欄位2,…… from 表名 [where 條件] //方式1
select * from 表名 [where 條件] //方式2
其中如果沒有where條件那麼就預設查詢整張表的內容,我們在這裡根據此條件查詢所有記錄:查詢返回年齡小於21歲的所有學生。
首先在sqlmanage中編寫getallstudent()函式,用來查詢student表中所有age小於21的記錄,並把查詢的資料最終以List<studnet>
型別返回:
public List<student> getallstudent() throws SQLException {
List<student>list=new ArrayList<student>();//返回的結果
String sql = "select * from student where age < 21";
PreparedStatement ps = con.prepareStatement(sql);
ResultSet resultSet=ps.executeQuery();//結果集
while(resultSet.next())//遍歷
{
int id=resultSet.getInt(1);
String name=resultSet.getString(2);
int age=resultSet.getInt(3);
int high=resultSet.getInt(4);
list.add(new student(id,name,age,high));
}
ps.close();
return list;
}
在前面講的插入的過程返回值其實不需要特別處理,因為返回是插入成功與否的訊息,而在查詢的步驟就要嚴格的跟著JDBC的6個步驟來—因為需要對返回的資料進行處理。我們主要通過ResultSet處理返回的資料。
在對ResultSet進行迭代遍歷取值的過程中,通過getXXX(int index)的方法取值並自動轉換為java對應的資料型別。而index為MySQL資料庫表格列的編號,也是資料在ResultSet中的對應序列號。
通過上面的函式在test單元測試中編寫selectTest() 測試函式在控制檯列印從資料庫中查詢所有age小於21的記錄:
@Test
public void selectTest() throws SQLException, ClassNotFoundException {
sqlmanage sqlmanage=new sqlmanage();
List<student>list=sqlmanage.getallstudent();
System.out.println(list.toString());
}
可以看到資料被成功查詢:
JDBC修改和刪除
修改資料
對某個確定的記錄修改,我們一般根據這條資訊的主鍵作為條件進行修改。而修改一般都需要條件語句where,否則修改整個表的內容。修改的MySQL語句為:
update 表名 set 欄位 = 值 [where條件]; -- 建議都有where: 不然的話會修改每一條資料
這裡我們假設將上述student表中所有age為12的記錄的name設定為xiaoming。在sqlmanage中編寫update()函式用來進行修改:
public void update() throws SQLException {
String sql = "update student set name='xiaoming' where age=12";
PreparedStatement ps = con.prepareStatement(sql);
ps.executeUpdate();
ps.close();
}
在tes單元測試中編寫updateTest()函式呼叫sqlmanage類的update()方法,將student表中所有age為12的記錄的name設為xiaoming。
@Test
public void updateTest() throws SQLException, ClassNotFoundException {
sqlmanage sqlmanage=new sqlmanage();
sqlmanage.update();
}
重新整理Navicat 你會發現資料被成功更新了:
刪除資料
JDBC刪除也是常用的一種操作,但刪除的操作一定要謹慎,謹防誤刪、多刪等操作。刪除的語句一般都有where條件,否則會刪除所有記錄。刪除的sql語句為:
delete from 表名 [where條件];
我們編寫一個按照id刪除記錄的函式,在sqlmanage中編寫deletebyid(int id),該函式意為根據id刪除student表中對應id的一條記錄:
public void deletebyid(int id) throws SQLException {
String sql = "delete from student where id = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1,id);
ps.executeUpdate();
ps.close();
}
這麼一個根據id刪除的函式就寫好了,我們在test單元測試中編寫deleteTest()測試函式刪除student表中id為1的那條記錄。:
@Test
public void deleteTest() throws SQLException, ClassNotFoundException {
sqlmanage sqlmanage=new sqlmanage();
sqlmanage.deletebyid(1);
}
執行完成檢視資料庫發現id為1的記錄(name為bigsai的記錄)被成功刪除:
總結與擴充
總結
好了,本次JDBC+MySQL的增刪改查的案例就到這裡了。回顧本課程你是不是覺得一切好像沒那麼難,只需要按部就班就可以完成整個案例。我們回顧一下整個流程:
- 建立資料庫和表
- 建立專案新增JDBC和Junit單元測試依賴
- 編寫專案程式碼(JDBC 6個步驟)
- 單元測試
每個流程代表一個知識點,其中最重要的就是要熟練掌握JDBC程式設計的流程了,掌握其方法,如果有所遺忘還得多多回顧。
擴充
MySQL本案例只使用了四種基本操作對應的sql語句:insert(插入),select(查詢),update(修改),delete(刪除)。如果需要深入學習MySQL的話很多方面需要深入挖掘,從sql語句上你還需要去學習MySQL複雜查詢例如關聯查詢、分組、排序等。從效能上要關注MySQL索引型別以及瞭解其底層資料結構與優勢。從安全性和資料一致性你要去了解學習MySQL髒讀、幻讀等以及各種鎖的使用……
而JDBC算是在Java中一種很原生處理MySQL的方式了,而到後面隨著學習的深入你會接觸兩個ORM框架—Mybatis和Hibernate,當然在國內Mybatis要更流行一些。這兩個框架是對JDBC的封裝,讓開發者能夠更容易的在應用中使用MySQL等關聯式資料庫,在Web專案有著廣泛的應用,無論是以前的SSH(Spring,Strus2,Hibernate)和現在流行的SSM(Spring,SpringMVC,Mybatis),其作為持久層的框架都是基於對JDBC的封裝處理。所以日後在學習新框架同時要記得回顧JDBC的內容,多掌握JDBC底層原理!
好啦,下課!我們們後會有期!
最後,本文收錄在公眾號:bigsai
中,更多精彩與資料與您分享,歡迎mark與您一起成長!同時也收錄在博學谷以關卡的新形式展現,歡迎嘗試!