干貨來襲|動力節(jié)點(diǎn)Java面試專項(xiàng)試題分享{含答案}-JDBC篇

以下是關(guān)于Java基礎(chǔ)面試題分享之JDBC面試題
001? 什么是JDBC?
JDBC的全稱是Java DataBase Connection,也就是Java數(shù)據(jù)庫連接,我們可以?它來操作關(guān)系型數(shù)據(jù)庫。JDBC接?及相關(guān)類在java.sql 包和javax.sql包?。我們可以?它來連接數(shù)據(jù)庫,執(zhí)?SQL查詢,存儲過程,并處理返回的結(jié)果。
JDBC接?讓Java程序和JDBC驅(qū)動實(shí)現(xiàn)了松耦合,使得切換不同的數(shù)據(jù)庫變得更加簡單。
002? 如何理解Class.forName(com.mysql.cj.jdbc.Driver)?
1.com.mysql.cj.jdbc.Driver是Driver驅(qū)動所在的位置,加載驅(qū)動
2.Class.forName()是一個(gè)反射,但是他沒有返回一個(gè)Class對象,因?yàn)槲覀儾恍枰?br>這是Driver的代碼:

它除了構(gòu)造方法,就只有一個(gè)靜態(tài)代碼塊,當(dāng)我們反射進(jìn)行的時(shí)候,這個(gè)類就開始初始化,他的靜態(tài)代碼塊內(nèi)容就已經(jīng)被執(zhí)行了,我們真正需要的是DriverManager.registerDriver(new Driver());這一行代碼
003? JDBC的DriverManager是用來做什么的?
是一個(gè)工廠類,我們通過它來創(chuàng)建數(shù)據(jù)庫連接,當(dāng)JDBC的Driver類被加載進(jìn)來時(shí),它會自己注冊到DriverManager類里面
004? 說下JDBC連接數(shù)據(jù)庫的6個(gè)步驟?
1.注冊驅(qū)動
2.獲取連接
3.創(chuàng)建一個(gè)Statement語句對象
4.執(zhí)行SQL語句
5.處理結(jié)果集
6.關(guān)閉資源
005? Statement 、PreparedStatement和CallableStatement的區(qū)別?
PreparedStatement 繼承于 Statement,Statement 一般用于執(zhí)行固定的沒有參數(shù)的SQL。
2.PreparedStatement 一般用于執(zhí)行有?參數(shù)預(yù)編譯的SQL語句。可以防止SQL注入,安全性高于Statement。
3.CallableStatement適用于執(zhí)行存儲過程。
006? execute,executeQuery,executeUpdate的區(qū)別是什么?
1)Statement的execute(String query)?法?來執(zhí)?任意的SQL查詢,如果查詢的結(jié)果是?個(gè)ResultSet,這個(gè)?法就返回true。如果結(jié)果不是ResultSet,?如insert或者update查詢,它就會返回false。
2)Statement的executeQuery(String query)接??來執(zhí)?select查詢,并且返回ResultSet。即使查詢不到記錄返回的ResultSet也不會為null。我們通常使?executeQuery來執(zhí)?查詢語句,這樣的話如果傳進(jìn)來的是insert或者update語句的 話,它會拋出錯誤信息為“executeQuery method can not be used for update”的java.util.SQLException。
3)Statement的executeUpdate(String query)?法?來執(zhí)?insert或者update/delete(DML)語句。
4)只有當(dāng)你不確定是什么語句的時(shí)候才應(yīng)該使?execute()?法,否則應(yīng)該使?executeQuery或者executeUpdate?法。
007? JDBC中大數(shù)據(jù)量的分頁解決方法?
最好的辦法是利用sql語句進(jìn)行分頁,這樣每次查詢出的結(jié)果集中就只包含某頁的數(shù)據(jù)內(nèi)容。
sql語句分頁,不同的數(shù)據(jù)庫下的分頁方案各不一樣,假設(shè)一共有38條數(shù)據(jù),每頁有10條數(shù)據(jù),查詢第3頁的數(shù)據(jù),下面是主流的三種數(shù)據(jù)庫的分頁sql:
Oracle:

mysql:
select * from students limit 20,10;

008? 在JDBC編程中處理事務(wù)的步驟?
事務(wù)是作為單個(gè)邏輯?作單元執(zhí)?的?系列操作,?個(gè)邏輯?作單元必須有四個(gè)屬性,稱為原?性、?致性、隔離性和持久性(ACID) 屬性,只有這樣才能成為?個(gè)事務(wù) 。JDBC處理事務(wù)有如下操作:
conn.setAutoComit(false);設(shè)置提交?式為??提交。
conn.commit()提交事務(wù)。
conn.rollback()回滾事務(wù)。
提交與回滾只選擇?個(gè)執(zhí)?。正常情況下提交事務(wù),如果出現(xiàn)異常,則回滾。
009? 說說數(shù)據(jù)庫連接池工作原理和實(shí)現(xiàn)方案?
數(shù)據(jù)庫連接是?種關(guān)鍵的有限的昂貴的資源,對數(shù)據(jù)庫連接的管理能顯著影響到整個(gè)應(yīng)?程序的伸縮性和健壯性,影響到程序 的性能指標(biāo)。數(shù)據(jù)庫連接池正是針對這個(gè)問題提出來的。
數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)?程序重復(fù)使??個(gè)現(xiàn)有的數(shù)據(jù)庫連接,?不是重新建??個(gè);釋放空閑時(shí)間超過最?空閑時(shí)間的數(shù)據(jù)庫連接來避免因?yàn)闆]有釋放數(shù)據(jù)庫連接?引起的數(shù)據(jù)庫連接遺漏。這項(xiàng)技術(shù)能明顯提?對數(shù)據(jù)庫操作的性能。
數(shù)據(jù)庫連接池在初始化時(shí)將創(chuàng)建?定數(shù)量的數(shù)據(jù)庫連接放到連接池中,這些數(shù)據(jù)庫連接的數(shù)量是由最?數(shù)據(jù)庫連接數(shù)來設(shè)定的。?論這些數(shù)據(jù)庫連接是否被使?,連接池都將?直保證?少擁有這么多的連接數(shù)量。連接池的最?數(shù)據(jù)庫連接數(shù)量限定了這個(gè)連接池能占有的最?連接數(shù),當(dāng)應(yīng)?程序向連接池請求的連接數(shù)超過最?連接數(shù)量時(shí),這些請求將被加?到等待隊(duì)列中。
010? jdbc規(guī)范使用到設(shè)計(jì)模式?
橋接模式,首先DriverManager獲得Connection是通過反射和類加載機(jī)制從數(shù)據(jù)庫驅(qū)動包的driver中拿到連接,所以這里真正參與橋接模式的是driver,而DriverManager和橋接模式?jīng)]有關(guān)系,DriverManager只是對driver的一個(gè)管理器。而我們作為使用者只去關(guān)心Connection,不會去關(guān)心driver,因?yàn)槲覀兊牟僮鞫际峭ㄟ^操作Connection來實(shí)現(xiàn)的。這樣分析下來這個(gè)橋接就清晰了邏輯——java.sql.Driver作為抽象橋類,而驅(qū)動包如com.mysql.jdbc.Driver具體的實(shí)現(xiàn)橋接類,而Connection是被橋接的對象。
011? JDBC的事務(wù)管理是什么,為什么需要它?
默認(rèn)情況下,我們創(chuàng)建的數(shù)據(jù)庫連接,是工作在自動提交的模式下的。這意味著只要我們執(zhí)行完一條查詢語句,就會自動進(jìn)行提交。因此我們的每條查詢,實(shí)際上都是一個(gè)事務(wù),如果我們執(zhí)行的是DML或者DDL,每條語句完成的時(shí)候,數(shù)據(jù)庫就已經(jīng)完成修改了。有的時(shí)候我們希望由一組SQL查詢組成一個(gè)事務(wù),如果它們都執(zhí)行OK我們再進(jìn)行提交,如果中途出現(xiàn)異常了,我們可以進(jìn)行回滾。
JDBC接口提供了一個(gè)setAutoCommit(boolean flag)方法,我們可以用它來關(guān)閉連接自動提交的特性。我們應(yīng)該在需要手動提交時(shí)才關(guān)閉這個(gè)特性,不然的話事務(wù)不會自動提交,每次都得手動提交。數(shù)據(jù)庫 通過表鎖來管理事務(wù),這個(gè)操作非常消耗資源。因此我們應(yīng)當(dāng)完成操作后盡快的提交事務(wù)。在這里有更多關(guān)于事務(wù)的示例程序。
012? JDBC里的CLOB和BLOB數(shù)據(jù)類型分別代表什么?
CLOB意思是Character Large OBjects,字符大對象,它是由單字節(jié)字符組成的字符串?dāng)?shù)據(jù),有自己專門的代碼頁。這種數(shù)據(jù)類型適用于存儲超長的文本信息,那些可能會超出標(biāo)準(zhǔn)的VARCHAR數(shù)據(jù)類型長度限制(上限是32KB)的文本。
BLOB是Binary Larget OBject,它是二進(jìn)制大對象,由二進(jìn)制數(shù)據(jù)組成,沒有專門的代碼頁。它能用于存儲超過VARBINARY限制(32KB)的二進(jìn)制數(shù)據(jù)。這種數(shù)據(jù)類型適合存儲圖片,聲音,圖形,或者其它業(yè)務(wù)程序特定的數(shù)據(jù)。
013? Java 中的反射是什么意思?有哪些應(yīng)用場景?
每個(gè)類都有一個(gè) Class 對象,包含了與類有關(guān)的信息。當(dāng)編譯一個(gè)新類時(shí),會產(chǎn)生一個(gè)同名的 .class 文件,該文件內(nèi)容保存著 Class 對象。類加載相當(dāng)于 Class 對象的加載,類在第一次使用時(shí)才動態(tài)加載到 JVM 中。也可以使用 Class.forName,這種方式來控制類的加載,該方法會返回一個(gè) Class 對象。
反射可以提供運(yùn)行時(shí)的類信息,并且這個(gè)類可以在運(yùn)行時(shí)才加載進(jìn)來,甚至在編譯時(shí)期該類的 .class 不存在也可以加載進(jìn)來。Class 和 java.lang.reflect 一起對反射提供了支持,java.lang.reflect 類庫主要包含了以下三個(gè)類:
(1)Field :可以使用 get() 和 set() 方法讀取和修改 Field 對象關(guān)聯(lián)的字段;
(2)Method :可以使用 invoke() 方法調(diào)用與 Method 對象關(guān)聯(lián)的方法;
(3)Constructor :可以用 Constructor 創(chuàng)建新的對象。
應(yīng)用舉例:工廠模式,使用反射機(jī)制,根據(jù)全限定類名獲得某個(gè)類的 Class 實(shí)例。
014? 什么是反射?
反射是用來描述類的信息的。對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為 Java 語言的反射機(jī)制。
015? 反射的范圍?
class:用來描述類本身
Packge:用來描述類所屬的包
Field:用來描述類中的屬性
Method:用來描述類中的方法
Constructor:用來描述類中的構(gòu)造方法
Annotation:用來描述類中的注解
016? 如何獲取Class?
1)Class clazz=class.forName("包名.類名")
2)Class clazz=類名.class;
3)Class clazz=對象.getClass();
017? 反射中常用的方法?
(1)獲取類的權(quán)限修飾符--------->int result=getModifiers();
(2)獲取名字------------>string name=clazz.getName();
(3)獲取包名------------>Packge p=clazz.getPackge();
(4)尋找clazz中無參數(shù)構(gòu)造方法:Clazz.getConstructor([String.class]);
? ? ?執(zhí)行構(gòu)造方法創(chuàng)建對象:Con.newInstance([參數(shù)]);
(5)Field c=cls.getFields():獲得某個(gè)類的所有的公共(public)的字段,包括父類中的字段。
? ? ?Field c=cls.getDeclaredFields():獲得某個(gè)類的所有聲明的字段,即包括public、private和 proteced,但是不包括父類的聲明字段。
018? 反射得利與弊?
(1)反射得經(jīng)典用法就是在xml或者properties配置文件中,然后在java類里面區(qū)解析這些內(nèi)容,得到一個(gè)字符串,然后通過反射機(jī)制,通過這些字符串獲得某個(gè)類得class實(shí)例,這樣的話就可以動態(tài)的配置一些東西,而不需要每次都重新去new,要改的話也是直接改配置文件,代碼維護(hù)起來方便很多。
(2)當(dāng)你在做一個(gè)軟件開發(fā)的插件的時(shí)候,你連插件的類型名稱都不知道,你怎么實(shí)例化這個(gè)對象呢?因?yàn)槌绦蚴侵С植寮模ǖ谌降模?,在開發(fā)的時(shí)候并不知道 。所以無法在代碼中 New出來 ,但反射可以,通過反射,動態(tài)加載程序集,然后讀出類,檢查標(biāo)記之后再實(shí)例化對象,就可以獲得正確的類實(shí)例。
(3)在編碼階段不知道那個(gè)類名,要在運(yùn)行期從配置文件讀取類名, 這時(shí)候就沒有辦法硬編碼new ClassName(),而必須用到反射才能創(chuàng)建這個(gè)對象.反射的目的就是為了擴(kuò)展未知的應(yīng)用。比如你寫了一個(gè)程序,這個(gè)程序定義了一些接口,只要實(shí)現(xiàn)了這些接口的dll都可以作為插件來插入到這個(gè)程序中。那么怎么實(shí)現(xiàn)呢?就可以通過反射來實(shí)現(xiàn)。就是把dll加載進(jìn)內(nèi)存,然后通過反射的方式來調(diào)用dll中的方法。很多工廠模式就是使用的反射。?
019? getName、getCanonicalName與getSimpleName的區(qū)別?
getSimpleName:只獲取類名?
getName:類的全限定名,jvm中Class的表示,可以用于動態(tài)加載Class對象,例如Class.forName。?
getCanonicalName:返回更容易理解的表示,主要用于輸出(toString)或log打印,大多數(shù)情況下和getName一樣,但是在內(nèi)部類、數(shù)組等類型的表示形式就不同了。