JDBC入门
1 概述
在Java中,數據庫存取技術可分為如下幾類:
- JDBC直接訪問數據庫
- JDO技術(Java Data Object)
- 第三方O/R工具,如Hibernate, Mybatis 等
JDBC是java訪問數據庫的基石,JDO, Hibernate等只是更好的封裝了JDBC。
1.1 什么是JDBC
JDBC(Java Database Connectivity)是一個獨立于特定數據庫管理系統(DBMS)、通用的SQL數據庫存取和操作的公共接口(一組API),定義了用來訪問數據庫的標準Java類庫,使用這個類庫可以以一種標準的方法、方便地訪問數據庫資源
JDBC為訪問不同的數據庫提供了一種統一的途徑 ,為開發者屏蔽了一些細節問題。
JDBC的目標是使Java程序員使用JDBC可以連接任何提供了JDBC驅動程序的數據庫系統,這樣就使得程序員無需對特定的數據庫系統的特點有過多的了解,從而大大簡化和加快了開發過程。
2 JDBC程序編寫步驟
- 注冊驅動
- 獲取連接
- 執行增刪改查
- 釋放資源
2.1 演示完整步驟
準備工作:引入JDBC驅動程序
驅動程序由數據庫提供商提供下載。 MySQL的驅動下載地址:http://dev.mysql.com/downloads/
以此點擊Connector/J→選擇Platform Independent→下載.zip文件→下載好的zip里的jar就是要的jar
-
(1)把mysql-connector-java-8.0.21.jar拷貝到項目中lib目錄中
-
(2)添加到項目的類路徑下
在驅動jar上右鍵–>Build Path–>Add to Build Path
注意:如果是Dynamic Web Project(動態的web項目)話,則是把驅動jar放到WebContent(有的開發工具叫WebRoot)目錄中的WEB-INF目錄中的lib目錄下即可
(一)加載并注冊驅動
加載并注冊驅動:
加載驅動,把驅動類加載到內存
注冊驅動,把驅動類的對象交給DriverManager管理,用于后面創建連接等使用。
- 1、Class.forName( )
因為 Driver 接口的驅動程序類都包含了靜態代碼塊,在這個靜態代碼塊中,會調用 DriverManager.registerDriver() 方法來注冊自身的一個實例,所以可以換一種方式來加載驅動。(即只要想辦法讓驅動類的這段靜態代碼塊執行即可注冊驅動類,而要讓這段靜態代碼塊執行,只要讓該類被類加載器加載即可)
調用 Class 類的靜態方法 forName(),向其傳遞要加載的 JDBC 驅動的類名
//通過反射,加載與注冊驅動類,解耦合(不直接依賴)
Class.forName(“com.mysql.jdbc.Driver”);
- 2、服務提供者框架(例如:JDBC的驅動程序)自動注冊(有版本要求)
符合JDBC 4.0規范的驅動程序包含了一個文件META-INF/services/java.sql.Driver,在這個文件中提供了JDBC驅動實現的類名。例如:mysql-connector-java-5.1.40-bin.jar文件中就可以找到java.sql.Driver文件,用文本編輯器打開文件就可以看到:com.mysql.jdbc.Driver類。
JVM的服務提供者框架在啟動應用時就會注冊服務,例如:MySQL的JDBC驅動就會被注冊,而原代碼中的Class.forName(“com.mysql.jdbc.Driver”)仍然可以存在,但是不會起作用。
但是注意mysql-connector-java-5.0.8-bin.jar版本的jar中沒有,如下
(二)獲取數據庫鏈接
可以通過 DriverManager 類建立到數據庫的連接Connection:
DriverManager 試圖從已注冊的 JDBC 驅動程序集中選擇一個適當的驅動程序。
例如:
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/girls?serverTimezone=UTC","root","root");JDBC URL 用于標識一個被注冊的驅動程序,驅動程序管理器通過這個 URL 選擇正確的驅動程序,從而建立到數據庫的連接。JDBC URL的標準由三部分組成,各部分間用冒號分隔。
jdbc:<子協議>:<子名稱>
- 協議:JDBC URL中的協議總是jdbc
- 子協議:子協議用于標識一個數據庫驅動程序
- 子名稱:一種標識數據庫的方法。子名稱可以依不同的子協議而變化,用子名稱的目的是為了定位數據庫提供足夠的信息
例如:
MySQL的連接URL編寫方式:
MySQL的連接URL之利用properties文件
在src下新建一個文件:jdbc.properties
(三)操作或訪問數據庫
數據庫連接被用于向數據庫服務器發送命令和 SQL 語句,并接受數據庫服務器返回的結果。
其實一個數據庫連接就是一個Socket連接。
在 java.sql 包中有 3 個接口分別定義了對數據庫的調用的不同方式:
- Statement:用于執行靜態 SQL 語句并返回它所生成結果的對象。
- PrepatedStatement:SQL 語句被預編譯并存儲在此對象中,然后可以使用此對象多次高效地執行該語句。
- CallableStatement:用于執行 SQL 存儲過程
3.1Statement
通過調用 Connection 對象的 createStatement() 方法創建該對象
該對象用于執行靜態的 SQL 語句,并且返回執行結果
Statement 接口中定義了下列方法用于執行 SQL 語句:
- int excuteUpdate(String sql):執行更新操作INSERT、UPDATE、DELETE,返回值為被改變的行數
- ResultSet excuteQuery(String sql):執行查詢操作SELECT
executeUpdate
package mysql;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;import com.mysql.jdbc.Driver;public class sqltest {public static void main(String[] args) throws SQLException, ClassNotFoundException {//1 加載驅動//DriverManager.registerDriver(new Driver());Class.forName("com.mysql.cj.jdbc.Driver");//2.獲取連接Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/girls?serverTimezone=UTC","root","root");//3.執行增刪改查//3-1 編寫sql語句String sql="UPDATE boys SET boyName='盧本偉' where id=1";//3-2 獲取執行sql語句的執行對象Statement statement= connection.createStatement();//3-3 使用命令對象指向sql語句int update=statement.executeUpdate(sql);//這一句只能增刪改,返回受影響行數//3-4處理執行結果System.out.println(update>0?"yes":"no");//4 關閉連接,后開先關閉,對稱statement.close();connection.close();}}ResultSet
通過調用 Statement 對象的 excuteQuery() 方法創建該對象
ResultSet 對象以邏輯表格的形式封裝了執行數據庫操作的結果集,ResultSet 接口由數據庫廠商實現
ResultSet 對象維護了一個指向當前數據行的游標,初始的時候,游標在第一行之前一行,可以通過 ResultSet 對象的 next() 方法移動到下一行
ResultSet 接口的常用方法:
- boolean next()
- getXxx(String columnLabel):columnLabel使用 SQL AS 子句指定的列標簽。如果未指定 SQL AS 子句,則標簽是列名稱
- getXxx(int index) :索引從1開始
3.2 PrepatedStatement
可以通過調用 Connection 對象的 preparedStatement(String sql) 方法獲取 PreparedStatement 對象
PreparedStatement 接口是 Statement 的子接口,它表示一條預編譯過的 SQL 語句
- PreparedStatement 對象所代表的 SQL 語句中的參數用問號(?)來表示,調用 PreparedStatement 對象的 setXxx() 方法來設置這些參數. setXxx() 方法有兩個參數,第一個參數是要設置的 SQL 語句中的參數的索引(從 1 開始),第二個是設置的 SQL 語句中的參數的值
- ResultSet executeQuery()執行查詢,并返回該查詢生成的 ResultSet 對象。
- int executeUpdate():執行更新,包括增、刪、改
↑來驗證賬戶密碼會導致sql注入問題,因為如果兩個參數中含有’ "等符號,會出現語法錯誤
↑就可以避免sql注入問題
2.2 封裝JDBCUtils.java
因為很多步驟都是重復的,所以可以將重復的操作封裝起來
import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties;/*** 此類是封裝JDBC連接的工具類* * 功能:* 1、獲取連接* 2、釋放資源**/ public class JDBCUtils {static String user;static String password;static String url;static String driver;static{try {Properties info = new Properties();info.load(new FileInputStream("src\\jdbc.properties"));user = info.getProperty("user");password = info.getProperty("password");url = info.getProperty("url");driver = info.getProperty("driver");//1.注冊驅動Class.forName(driver);} catch (Exception e) {throw new RuntimeException(e);}}/*** 功能:獲取可用的連接對象* @return 連接* @throws Exception*/public static Connection getConnection(){try {return DriverManager.getConnection(url, user, password);} catch (Exception e) {throw new RuntimeException(e);}}/*** 功能:釋放資源* @param set* @param statement* @param connection* @throws Exception*/public static void close(ResultSet set,Statement statement,Connection connection){try {if (set!=null) {set.close();//如果是查詢操作,需要關閉set,否則這里傳個null}if (statement!=null) {statement.close();}if (connection!=null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}}至此以下為完整步驟
3 JDBC事務
package com.atguigu.jdbc2;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;import org.junit.Test;import com.atguigu.jdbc1.JDBCUtils;/*** 此類用于演示JDBC中的事務* @author liyuting* * 使用步驟:* 1、開啟新事務* 取消隱式事務自動提交的功能* setAutoCommit(false);* 2、編寫組成事務的一組sql語句* * 3、結束事務* commit();提交* rollback();回滾* * 細節:* 要求開啟事務的連接對象和獲取命令的連接對象必須是同一個!否則事務無效* * * * * * 案例:轉賬案例* 張三豐給滅絕轉5000* **/ public class TestTransaction {//不用事務@Testpublic void testNoTransaction() throws Exception{//1.獲取連接Connection connection = JDBCUtils.getConnection();//2.執行sql語句PreparedStatement statement = connection.prepareStatement("update account set balance = ? where stuname=?");//操作1:張三豐的錢-5000statement.setDouble(1, 5000);statement.setString(2, "張三豐");statement.executeUpdate();int i = 1/0;//模擬異常//操作2:張三豐的錢-5000statement.setDouble(1, 15000);statement.setString(2, "滅絕師太");statement.executeUpdate();//3.釋放資源JDBCUtils.close(null, statement, connection);}//使用事務@Testpublic void testTransaction(){Connection connection = null;PreparedStatement statement = null;try {//1.獲取連接connection = JDBCUtils.getConnection();//①事務的使用步驟1:開啟事務,意思是取消每條語句自動commitconnection.setAutoCommit(false);//②事務的使用步驟2:編寫sql語句,并且執行statement = connection.prepareStatement("update account set balance = ? where stuname=?");//操作1:張三豐的錢-5000statement.setDouble(1, 5000);statement.setString(2, "張三豐");statement.executeUpdate();// int i = 1/0;//模擬異常//操作2:張三豐的錢-5000statement.setDouble(1, 15000);statement.setString(2, "滅絕師太");statement.executeUpdate();//③事務的使用步驟3:結束事務connection.commit();} catch (SQLException e) {try {//回滾事務connection.rollback();} catch (SQLException e1) {e1.printStackTrace();}}finally{JDBCUtils.close(null, statement, connection);}}}4 批處理
當需要成批插入或者更新記錄時。可以采用Java的批量更新機制,這一機制允許多條語句一次性提交給數據庫批量處理。通常情況下比單獨提交處理更有效率。
JDBC的批量處理語句包括下面兩個方法:
- addBatch():添加需要批量處理的SQL語句或參數
- executeBatch():執行批量處理語句;
- clearBatch():清空批處理包的語句
分為兩種情況:
5 Blob類型數據
MySQL中,BLOB是一個二進制大型對象,是一個可以存儲大量數據的容器,它能容納不同大小的數據。能夠存
MySQL的四種BLOB類型(除了在存儲的最大信息量上不同外,他們是等同的)
實際使用中根據需要存入的數據大小定義不同的BLOB類型。
需要注意的是:如果存儲的文件過大,數據庫的性能會下降
6 數據庫連接池
(1)數據庫連接池的必要性
不使用數據庫連接池存在的問題:
- 普通的JDBC數據庫連接使用 DriverManager 來獲取,每次向數據庫建立連接的時候都要將 Connection 加載到內存中,再驗證IP地址,用戶名和密碼(得花費0.05s~1s的時間)。需要數據庫連接的時候,就向數據庫要求一個,執行完成后再斷開連接。這樣的方式將會消耗大量的資源和時間。數據庫的連接資源并沒有得到很好的重復利用.若同時有幾百人甚至幾千人在線,頻繁的進行數據庫連接操作將占用很多的系統資源,嚴重的甚至會造成服務器的崩潰。
- 對于每一次數據庫連接,使用完后都得斷開。否則,如果程序出現異常而未能關閉,將會導致數據庫系統中的內存泄漏,最終將導致重啟數據庫。
- 這種開發不能控制被創建的連接對象數,系統資源會被毫無顧及的分配出去,如連接過多,也可能導致內存泄漏,服務器崩潰。
為解決傳統開發中的數據庫連接問題,可以采用數據庫連接池技術(connection pool)。
數據庫連接池的基本思想就是為數據庫連接建立一個“緩沖池”。預先在緩沖池中放入一定數量的連接,當需要建立數據庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去。數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重復使用一個現有的數據庫連接,而不是重新建立一個。連接池的最大數據庫連接數量限定了這個連接池能占有的最大連接數,當應用程序向連接池請求的連接數超過最大連接數量時,這些請求將被加入到等待隊列中。
數據庫連接池技術的優點:
- 資源重用:
- 由于數據庫連接得以重用,避免了頻繁創建,釋放連接引起的大量性能開銷。在減少系統消耗的基礎上,另一方面也增加了系統運行環境的平穩性。
- 更快的系統反應速度
- 數據庫連接池在初始化過程中,往往已經創建了若干數據庫連接置于連接池中備用。此時連接的初始化工作均已完成。對于業務請求處理而言,直接利用現有可用連接,避免了數據庫連接初始化和釋放過程的時間開銷,從而減少了系統的響應時間
- 新的資源分配手段
- 對于多應用共享同一數據庫的系統而言,可在應用層通過數據庫連接池的配置,實現某一應用最大可用數據庫連接數的限制,避免某一應用獨占所有的數據庫資源
- 統一的連接管理,避免數據庫連接泄露
- 在較為完善的數據庫連接池實現中,可根據預先的占用超時設定,強制回收被占用連接,從而避免了常規數據庫連接操作中可能出現的資源泄露
(2)多種開源的數據庫連接池
JDBC 的數據庫連接池使用 javax.sql.DataSource 來表示,DataSource 只是一個接口,該接口通常由服務器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實現:
- DBCP 是Apache提供的數據庫連接池,速度相對c3p0較快,但因自身存在BUG,Hibernate3已不再提供支持
- C3P0 是一個開源組織提供的一個數據庫連接池,速度相對較慢,穩定性還可以
- Proxool 是sourceforge下的一個開源項目數據庫連接池,有監控連接池狀態的功能,穩定性較c3p0差一點
- BoneCP 是一個開源組織提供的數據庫連接池,速度快
- Druid是阿里提供的數據庫連接池,據說是集DBCP 、C3P0 、Proxool 優點于一身的數據庫連接池,但是速度不知道是否有BoneCP快
DataSource 通常被稱為數據源,它包含連接池和連接池管理兩個部分,習慣上也經常把 DataSource 稱為連接池
注意: - 數據源和數據庫連接不同,數據源無需創建多個,它是產生數據庫連接的工廠,因此整個應用只需要一個數據源即可。
- 當數據庫訪問結束后,程序還是像以前一樣關閉數據庫連接:conn.close(); 但conn.close()并沒有關閉數據庫的物理連接,它僅僅把數據庫連接釋放,歸還給了數據庫連接池。
(3)Druid(德魯伊)數據源
Druid是阿里巴巴開源平臺上一個數據庫連接池實現,它結合了C3P0、DBCP、Proxool等DB池的優點,同時加入了日志監控,可以很好的監控DB池連接和SQL的執行情況,可以說是針對監控而生的DB連接池,據說是目前最好的連接池。
properties文件👇
url=jdbc:mysql://localhost:3306/0319db username=root password=123456 driverClassName=com.mysql.jdbc.Driver initialSize=10 maxActive=20 maxWait=1000 filters=wall| name | 配置這個屬性的意義在于,如果存在多個數據源,監控的時候可以通過名字來區分開來。 如果沒有配置,將會生成一個名字,格式是:”DataSource-” + System.identityHashCode(this) | |
| jdbcUrl | 連接數據庫的url,不同數據庫不一樣。例如:mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto | |
| username | 連接數據庫的用戶名 | |
| password | 連接數據庫的密碼。如果你不希望密碼直接寫在配置文件中,可以使用ConfigFilter。詳細看這里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter | |
| driverClassName | 根據url自動識別 這一項可配可不配,如果不配置druid會根據url自動識別dbType,然后選擇相應的driverClassName(建議配置下) | |
| initialSize | 0 | 初始化時建立物理連接的個數。初始化發生在顯示調用init方法,或者第一次getConnection時 |
| maxActive | 8 | 最大連接池數量 |
| maxIdle | 8 | 已經不再使用,配置了也沒效果 |
| minIdle | 最小連接池數量 | |
| maxWait | 獲取連接時最大等待時間,單位毫秒。配置了maxWait之后,缺省啟用公平鎖,并發效率會有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。 | |
| poolPreparedStatements | false | 是否緩存preparedStatement,也就是PSCache。PSCache對支持游標的數據庫性能提升巨大,比如說oracle。在mysql下建議關閉。 |
| maxOpenPreparedStatements | -1 | |
| validationQuery | 用來檢測連接是否有效的sql,要求是一個查詢語句。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會其作用。 | |
| testOnBorrow | true | 申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。 |
| testOnReturn | false | 歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能 |
| testWhileIdle | false | 建議配置為true,不影響性能,并且保證安全性。申請連接的時候檢測,如果空閑時間大于timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。 |
| timeBetweenEvictionRunsMillis | 有兩個含義: 1)Destroy線程會檢測連接的間隔時間2)testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明 | |
| numTestsPerEvictionRun | 不再使用,一個DruidDataSource只支持一個EvictionRun | |
| minEvictableIdleTimeMillis | ||
| connectionInitSqls | 物理連接初始化的時候執行的sql | |
| exceptionSorter | 根據dbType自動識別 當數據庫拋出一些不可恢復的異常時,拋棄連接 | |
| filters | 屬性類型是字符串,通過別名的方式配置擴展插件,常用的插件有: 監控統計用的filter:stat日志用的filter:log4j防御sql注入的filter:wall | |
| proxyFilters | 類型是List,如果同時配置了filters和proxyFilters,是組合關系,并非替換關系 |
7 利用Druid的CRUD封裝
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List;import com.atguigu.bean.Boys;/*** 此類用于封裝通用的增刪改查方法* @author liyuting* 功能:* 1、執行增刪改* 2、執行查詢* * */ public class CRUDUtils {/*** 功能:增刪改* 針對于任何表的任何增刪改語句* @return* @throws Exception */public static int update(String sql,Object...params){try {//1.獲取連接Connection connection = JDBCUtilsByDruid.getConnection();//2.執行sql語句PreparedStatement statement = connection.prepareStatement(sql);for (int i = 0; i < params.length; i++) {statement.setObject(i+1, params[i]);}int update = statement.executeUpdate();return update;} catch (Exception e) {throw new RuntimeException(e);}}/*** orm:object relation mapping* @param sql* @param params* @return* * 只針對Boys表,查詢單條* @throws Exception */public static Boys querySingle(String sql,Object...params) throws Exception{Connection connection=null;PreparedStatement statement=null;ResultSet set = null;try {//1.獲取連接connection = JDBCUtilsByDruid.getConnection();//2.執行查詢statement = connection.prepareStatement(sql);for (int i = 0; i < params.length; i++) {statement.setObject(i+1, params[i]);}set = statement.executeQuery();if(set.next()){int id = set.getInt("id");String boyName = set.getString("boyname");int userCP = set.getInt("userCP");Boys bo = new Boys(id,boyName,userCP);return bo;}return null;} catch (Exception e) {throw new RuntimeException(e);}finally{JDBCUtilsByDruid.close(set, statement, connection);}}/*** orm:object relation mapping* @param sql* @param params* @return* * 只針對Boys表,查詢多條* @throws Exception */public static List<Boys> queryMulti(String sql,Object...params) throws Exception{Connection connection=null;PreparedStatement statement=null;ResultSet set = null;try {//1.獲取連接connection = JDBCUtilsByDruid.getConnection();//2.執行查詢statement = connection.prepareStatement(sql);for (int i = 0; i < params.length; i++) {statement.setObject(i+1, params[i]);}set = statement.executeQuery();List<Boys> list = new ArrayList<>();while(set.next()){int id = set.getInt("id");String boyName = set.getString("boyname");int userCP = set.getInt("userCP");Boys bo = new Boys(id,boyName,userCP);list.add(bo);}return list;} catch (Exception e) {throw new RuntimeException(e);}finally{JDBCUtilsByDruid.close(set, statement, connection);}}}boys類👇
package com.atguigu.bean;public class Boys {private int id;private String boyName;private int userCP;public Boys() {super();}@Overridepublic String toString() {return "Boys [id=" + id + ", boyName=" + boyName + ", userCP=" + userCP + "]";}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getBoyName() {return boyName;}public void setBoyName(String boyName) {this.boyName = boyName;}public int getUserCP() {return userCP;}public void setUserCP(int userCP) {this.userCP = userCP;}public Boys(int id, String boyName, int userCP) {super();this.id = id;this.boyName = boyName;this.userCP = userCP;}}👇調用實例
package com.atguigu.utils;import java.util.List;import org.junit.Test;import com.atguigu.bean.Boys;public class TestCRUDUtils {@Testpublic void testUpdate(){// int update = CRUDUtils.update("update beauty set sex = ? where name='柳巖'", "男"); // // System.out.println(update>0?"success":"failure");int update = CRUDUtils.update("delete from admin where id>5");System.out.println(update>0?"success":"failure");}@Testpublic void testQuery() throws Exception{ // Boys boy = CRUDUtils.querySingle("select * from boys where id = ?", 2); // System.out.println(boy);List<Boys> list = CRUDUtils.queryMulti("select * from boys");for (Boys boys : list) {System.out.println(boys);}}}8 DBUtils
commons-dbutils是 Apache 組織提供的一個開源 JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,并且使用dbutils能極大簡化jdbc編碼的工作量,同時也不會影響程序的性能。
1、DbUtils類
DbUtils :提供如關閉連接、裝載JDBC驅動程序等常規工作的工具類,里面的所有方法都是靜態的。主要方法如下:
- public static void close(…) throws java.sql.SQLException: DbUtils類提供了三個重載的關閉方法。這些方法檢查所提供的參數是不是NULL,如果不是的話,它們就關閉Connection、Statement和ResultSet。
- public static void closeQuietly(…): 這一類方法不僅能在Connection、Statement和ResultSet為NULL情況下避免關閉,還能隱藏一些在程序中拋出的SQLEeception。
- public static void commitAndClose(Connection conn)throws SQLException 用來提交連接的事務,然后關閉連接
- public static void commitAndCloseQuietly(Connection conn): 用來提交連接的事務,然后關閉連接,并且在關閉連接時不拋出SQL異常。
- public static void rollback(Connection conn)throws SQLException允許conn為null,因為方法內部做了判斷
- public static void rollbackAndClose(Connection conn)throws SQLException
- rollbackAndCloseQuietly(Connection)
- public static boolean loadDriver(java.lang.String driverClassName):這一方裝載并注冊JDBC驅動程序,如果成功就返回true。使用該方法,你不需要捕捉這個異常ClassNotFoundException。
2、QueryRunner類
該類封裝了SQL的執行,是線程安全的。
(1)可以實現增、刪、改、查、批處理、
(2)考慮了事務處理需要共用Connection。
(3)該類最主要的就是簡單化了SQL查詢,它與ResultSetHandler組合在一起使用可以完成大部分的數據庫操作,能夠大大減少編碼量。
QueryRunner類提供了兩個構造方法:
- QueryRunner():默認的構造方法
- QueryRunner(DataSource ds):需要一個 javax.sql.DataSource 來作參數的構造方法。
(1)更新 - public int update(Connection conn, String sql, Object… params) throws SQLException:用來執行一個更新(插入、更新或刪除)操作。
(2)插入 - public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT語句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自動生成的鍵值
(3)批處理 - public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE語句
- public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT語句
(4)使用QueryRunner類實現查詢 - public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:執行一個查詢操作,在這個查詢中,對象數組中的每個元素值被用來作為查詢語句的置換參數。該方法會自行處理 PreparedStatement 和 ResultSet 的創建和關閉。
3、ResultSetHandler接口
該接口用于處理 java.sql.ResultSet,將數據按要求轉換為另一種形式。ResultSetHandler 接口提供了一個單獨的方法:Object handle (java.sql.ResultSet rs)該方法的返回值將作為QueryRunner類的query()方法的返回值。
該接口有如下實現類可以使用: - ArrayHandler:把結果集中的第一行數據轉成對象數組。
- ArrayListHandler:把結果集中的每一行數據都轉成一個數組,再存放到List中。
- BeanHandler:將結果集中的第一行數據封裝到一個對應的JavaBean實例中。
- BeanListHandler:將結果集中的每一行數據都封裝到一個對應的JavaBean實例中,存放到List里。
- ColumnListHandler:將結果集中某一列的數據存放到List中。
- KeyedHandler(name):將結果集中的每一行數據都封裝到一個Map里,再把這些map再存到一個map里,其key為指定的key。
- MapHandler:將結果集中的第一行數據封裝到一個Map里,key是列名,value就是對應的值。
- MapListHandler:將結果集中的每一行數據都封裝到一個Map里,然后再存放到List
4、表與JavaBean
👇舉例代碼
9 DAO和增刪改查通用方法
DAO:Data Access Object訪問數據信息的類和接口,包括了對數據的CRUD(Create、Retrival、Update、Delete),而不包含任何業務相關的信息
作用:為了實現功能的模塊化,更有利于代碼的維護和升級。
👆只是基礎的增刪查改,適合于任何的類,還需要對每一張表定義一個實體類,然后用不同的類DAO繼承basicdao
比如說adminDAO,Admin指定了泛型
然后再AdminService里面
package com.atguigu.service;import com.atguigu.dao.AdminDao;public class AdminService {AdminDao dao = new AdminDao();public boolean login(String username,String password){Long count = (Long)dao.scalar("select count(*) from admin where username=? and password=?", username,password);return count>0;}}👇最后再在view層調用
package com.atguigu.view;import java.util.Scanner;import com.atguigu.service.AdminService;public class StudentView {AdminService as = new AdminService();public static void main(String[] args) {new StudentView().login();}public void login(){Scanner input = new Scanner(System.in);System.out.println("請輸入用戶名:");String username = input.next();System.out.println("請輸入密碼:");String password = input.next();if( as.login(username, password)){System.out.println("登錄成功!");showMainMenu();}else{System.out.println("登錄失敗!");}}/*** 功能:顯示主菜單*/private void showMainMenu() {System.out.println("顯示主菜單");} }總結
- 上一篇: 思维导图下载 注册安全_【思维导图】初中
- 下一篇: pb mysql 中文乱码_解决spri