【Java数据库】使用JDBC操作MySQL数据库、Batch批处理 、事务的概念
MySQL 數(shù)據(jù)庫(kù)的命令行操作
登陸操作mysql -hlocalhost –uroot –p123456
退出操作exit
數(shù)據(jù)庫(kù)操作建庫(kù):create database 庫(kù)名;
卸載庫(kù):drop database 庫(kù)名;
顯示所有數(shù)據(jù)庫(kù):show databases;
選擇庫(kù):use testjdbc;
表操作建表的sql語(yǔ)句
顯示庫(kù)中所有表:show tables;
顯示某個(gè)表的結(jié)構(gòu):describe testjdbc;
SQL操作select語(yǔ)句;insert語(yǔ)句; update語(yǔ)句; delete語(yǔ)句;
表操作DDL語(yǔ)句(create, alter, drop等);
Java使用JDBC
先下載一個(gè)mysql-connector-java-8.0.16.jar,其他版本也行
把這個(gè)jar添加到Java Build Path中(我為了避免以后移動(dòng)jar的時(shí)候找不到,就直接復(fù)制到項(xiàng)目路徑下了)
JDBC常用接口
(1)Driver接口
– Driver接口由數(shù)據(jù)庫(kù)廠家提供,對(duì)于java開發(fā)者而言,只需要使用
Driver接口就可以了。
– 在編程中要連接數(shù)據(jù)庫(kù),必須先裝載特定廠商的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序。不
同的數(shù)據(jù)庫(kù)有不同的裝載方法。
– 驅(qū)動(dòng):就是各個(gè)數(shù)據(jù)庫(kù)廠商實(shí)現(xiàn)的Sun公司提出的JDBC接口。 即對(duì)
Connection等接口的實(shí)現(xiàn)類的jar文件
– 裝載MySql驅(qū)動(dòng)
? Class.forName("com.mysql.jdbc.Driver");
– 裝載Oracle驅(qū)動(dòng)
? Class.forName("oracle.jdbc.driver.OracleDriver");
(2)DriverManager接口
– DriverManager是JDBC的管理層,作用于用戶和驅(qū)動(dòng)程序之間。
– DriverManager跟蹤可用的驅(qū)動(dòng)程序,并在數(shù)據(jù)庫(kù)和相應(yīng)的驅(qū)動(dòng)程序
之間建立連接。
(3)Connection接口
– Connection與特定數(shù)據(jù)庫(kù)的連接(會(huì)話),在連接上下文中執(zhí)行 SQL
語(yǔ)句并返回結(jié)果。
– DriverManager的getConnection()方法建立在JDBC URL中定義的數(shù)
據(jù)庫(kù)Connection連接上
– 連接MYSQL數(shù)據(jù)庫(kù):
– 連接ORACLE數(shù)據(jù)庫(kù):
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@host:port:databse","user","password");注意:建立connection是比較耗時(shí)、耗資源的,(連接對(duì)象內(nèi)部其實(shí)包含的Socket對(duì)象,是一個(gè)遠(yuǎn)程的連接,比較耗時(shí)!這是Connection對(duì)象管理的一個(gè)要點(diǎn)!)經(jīng)過(guò)測(cè)試,在本機(jī)上建立鏈接,耗時(shí)235ms。在真正的開發(fā)中,為了提高效率,都會(huì)使用連接池來(lái)管理連接對(duì)象!
(4)Statement接口:用于執(zhí)行SQL語(yǔ)句、返回結(jié)果,是查詢操作的核心
– 用于執(zhí)行靜態(tài) SQL 語(yǔ)句并返回它所生成結(jié)果的對(duì)象。
– 三種Statement類:
? Statement:
– 由createStatement創(chuàng)建,用于發(fā)送簡(jiǎn)單的SQL語(yǔ)句。(不帶參數(shù)的)
? PreparedStatement:
– 繼承自Statement接口,由prepareStatement創(chuàng)建,用于發(fā)送含有一個(gè)或多個(gè)輸入?yún)?shù)的sql語(yǔ)句。PreparedStatement對(duì)象比Statement對(duì)象的效率更高,并且可以防止SQL注入。我們一般都用PreparedStatement.
? CallableStatement:
– 繼承自PreparedStatement 。由方法prePareCall創(chuàng)建,用于調(diào)用存儲(chǔ)過(guò)程。
– 常用的Statement方法:
? execute():運(yùn)行語(yǔ)句,返回是否有結(jié)果集。
? executeQuery():運(yùn)行select語(yǔ)句,返回ResultSet結(jié)果集。
? executeUpdate():運(yùn)行insert/update/delete操作,返回更新的行數(shù)。
Java中連接數(shù)據(jù)庫(kù)的使用示例
// 測(cè)試MySQL的連接 package cn.hanquan.jdbcTest;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;public class JDBCTest {public static void main(String[] args) {try {// 加載驅(qū)動(dòng)類Class.forName("com.mysql.cj.jdbc.Driver");// 建立鏈接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root", "123456");// sql包中的接口System.out.println(conn);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}} }- 常見問(wèn)題(1)
The server time zone value ‘?й???’ is unrecognized or represents more than one time zone.
- 解決方式
使用的數(shù)據(jù)庫(kù)是MySQL,驅(qū)動(dòng)是8.0.16,這是由于數(shù)據(jù)庫(kù)和系統(tǒng)時(shí)區(qū)差異所造成的。
在jdbc連接的url后面加上serverTimezone=GMT即可解決問(wèn)題:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root", "123456");// sql包中的接口如果需要使用gmt+8時(shí)區(qū),需要寫成GMT%2B8,否則會(huì)被解析為空。
再一個(gè)解決辦法就是:使用低版本的MySQL jdbc驅(qū)動(dòng),5.1.28不會(huì)存在時(shí)區(qū)的問(wèn)題。
- 常見問(wèn)題(2)
Loading class ‘com.mysql.jdbc.Driver’. This is deprecated. The new driver class is ‘com.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
- 解決方式
將Class.forName("com.mysql.jdbc.Driver");替換成Class.forName("com.mysql.cj.jdbc.Driver");即可
執(zhí)行SQL語(yǔ)句示例
- 向表中插入一條數(shù)據(jù)
實(shí)際開發(fā)中,使用Statement比較少,因?yàn)閰?shù)需要拼接字符串來(lái)做。處理參數(shù)不方便。
另外,使用Statement容易發(fā)生SQL注入的危險(xiǎn)。
為了避免注入,我們使用PreparedStatement
? execute():運(yùn)行語(yǔ)句,返回是否有結(jié)果集。
? executeQuery():運(yùn)行select語(yǔ)句,返回ResultSet結(jié)果集。
? executeUpdate():運(yùn)行insert/update/delete操作,返回更新的行數(shù)。
- 查找數(shù)據(jù),返回結(jié)果集
關(guān)于rs.next()的說(shuō)明
代碼
輸出
老高 222222 110 2019-08-11 高淇 888888 119 2019-08-11批處理 Batch:20000條數(shù)據(jù)大約2秒
對(duì)于大量的批處理,建議使用Statement,因?yàn)镻reparedStatement的預(yù)編譯空間有限,當(dāng)數(shù)據(jù)量特別大時(shí),會(huì)發(fā)生異常。
package cn.hanquan.jdbcTest;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class JDBCTest {public static void main(String[] args) {Connection conn = null;Statement stat = null;try {// 加載驅(qū)動(dòng)類Class.forName("com.mysql.cj.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root","123456");conn.setAutoCommit(false);// 把事務(wù)設(shè)置為手動(dòng)提交stat = conn.createStatement();for (int i = 0; i < 100; i++) {stat.addBatch("INSERT INTO user (id, pwd, phone, date) VALUES ('批量" + i + "', 'password', 100000, now());");}stat.executeBatch();conn.commit();// 提交事務(wù)} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (stat != null) {stat.close();}} catch (SQLException e) {e.printStackTrace();}try {if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}} }事務(wù)的概念
一組事務(wù)要么同時(shí)執(zhí)行成功,要么同時(shí)執(zhí)行失敗的SQL語(yǔ)句。是數(shù)據(jù)庫(kù)操作的一個(gè)執(zhí)行單元!
– 事務(wù)開始于:
? 連接到數(shù)據(jù)庫(kù)上,并執(zhí)行一條DML語(yǔ)句(INSERT、UPDATE或DELETE)。
? 前一個(gè)事務(wù)結(jié)束后,又輸入了另外一條DML語(yǔ)句。
– 事務(wù)結(jié)束于:
? 執(zhí)行COMMIT或ROLLBACK語(yǔ)句。
? 執(zhí)行一條DDL語(yǔ)句,例如CREATE TABLE語(yǔ)句;在這種情況下,會(huì)自動(dòng)執(zhí)行COMMIT語(yǔ)句。
? 執(zhí)行一條DCL語(yǔ)句,例如GRANT語(yǔ)句;在這種情況下,會(huì)自動(dòng)執(zhí)行COMMIT語(yǔ)句。
? 斷開與數(shù)據(jù)庫(kù)的連接。
? 執(zhí)行了一條DML語(yǔ)句,該語(yǔ)句卻失敗了;在這種情況中,會(huì)為這個(gè)無(wú)效的DML語(yǔ)句執(zhí)行ROLLBACK語(yǔ)句。
事務(wù)的四大特點(diǎn)(ACID)
– atomicity(原子性)
? 表示一個(gè)事務(wù)內(nèi)的所有操作是一個(gè)整體,要 么全部成功,要么全失敗;
– consistency(一致性)
? 表示一個(gè)事務(wù)內(nèi)有一個(gè)操作失敗時(shí),所有的更改過(guò)的數(shù)據(jù)都必須回滾到修改前的狀態(tài);
– isolation(隔離性)
? 事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務(wù)修改它之前的狀態(tài),要么是另一事務(wù)修改它之后的狀態(tài),事務(wù)不會(huì)查看中間狀態(tài)的數(shù)據(jù)。
– durability(持久性)
? 持久性事務(wù)完成之后,它對(duì)于系統(tǒng)的影響是永久性的。
事務(wù)隔離級(jí)別從低到高:
– 讀取未提交(Read Uncommitted)
– 讀取已提交(Read Committed)
– 可重復(fù)讀(Repeatable Read)
– 序列化(serializable)
代碼示例:使用事務(wù),如果某一條語(yǔ)句執(zhí)行失敗,自動(dòng)回滾conn.rollback()
package cn.hanquan.jdbcTest;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException;public class JDBCTest {public static void main(String[] args) throws SQLException {Connection conn = null;PreparedStatement ps1 = null;try {// 加載驅(qū)動(dòng)類Class.forName("com.mysql.cj.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root","123456");conn.setAutoCommit(false);// 將事務(wù)設(shè)置為手動(dòng)提交for (int i = 0; i < 10; i++) {ps1 = conn.prepareStatement("INSERT INTO user (id, pwd, phone, date) VALUES (?, ?, ?, now());");ps1.setObject(1, "auto" + i);ps1.setObject(2, "000000" + i);ps1.setObject(3, "10000" + i);ps1.execute();}conn.commit();// 提交事務(wù)} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();conn.rollback();// 執(zhí)行失敗 回滾 我測(cè)試了一下 如果不加這句話 也會(huì)自動(dòng)回滾 不知道為啥} finally {try {if (ps1 != null) {ps1.close();}} catch (SQLException e) {e.printStackTrace();}try {if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}} }總結(jié)
以上是生活随笔為你收集整理的【Java数据库】使用JDBC操作MySQL数据库、Batch批处理 、事务的概念的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Java正则表达式】正则基本语法、使用
- 下一篇: 【MySQL查询】复杂查询:别名、外键j