前言
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://:/?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 ,頭條號:碼農bigsai 中更多精彩與資料與您分享,歡迎mark與您一起成長!同時也收錄在博學谷以關卡的新形式展現,歡迎嘗試!如果有用,歡迎關注、點贊、轉發一鍵三聯,將知識分享是我不斷努力的源源動力!