本文是銜接上文(史上最全的Java面試題總匯,不再懼怕面試官,成功坐等offer)的帶答案版本,答案已經整理完畢。希望大家采納。
本文內容偏多,建議收藏閱讀。 小編整理不易,給個關注吧~
四、反射
57.什么是反射?
Java反射就是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;并且能改變它的屬性。而這也是Java被視為動態(或準動態,為啥要說是準動態,因為一般而言的動態語言定義是程序運行時,允許改變程序結構或變量類型,這種語言稱為動態語言。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。)語言的一個關鍵性質。
58.什么是 java 序列化?什么情況下需要序列化?
?序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸于網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
當 Java 對象需要在網絡上傳輸 或者 持久化存儲到文件中時,就需要對 Java 對象進行序列化處理。
59.動態代理是什么?有哪些應用?
動態代理:當想要給實現了某個接口的類中的方法,加一些額外的處理。比如說加日志,加事務等。可以給這個類創建一個代理,故名思議就是創建一個新的類,這個類不僅包含原來類方法的功能,而且還在原來的基礎上添加了額外處理的新類。這個代理類并不是定義好的,是動態生成的。具有解耦意義,靈活,擴展性強。
動態代理的應用:Spring的AOP,加事務,加權限,加日志。
60.怎么實現動態代理?
動態代理實現:首先必須定義一個接口,還要有一個InvocationHandler(將實現接口的類的對象傳遞給它)處理類。再有一個工具類Proxy(習慣性將其稱為代理類,因為調用他的newInstance()可以產生代理對象,其實他只是一個產生代理對象的工具類)。利用到InvocationHandler,拼接代理類源碼,將其編譯生成代理類的二進制碼,利用加載器加載,并將其實例化產生代理對象,最后返回。
五、對象拷貝
61.為什么要使用克隆?
想對一個對象進行處理,又想保留原有的數據進行接下來的操作,就需要克隆了。克隆分淺克隆和深克隆,淺克隆后的對象中非基本對象和原對象指向同一塊內存,因此對這些非基本對象的修改會同時更改克隆前后的對象。深克隆可以實現完全的克隆,可以用反射的方式或序列化的方式實現。
62.如何實現對象克隆?
有兩種方式: 1). 實現Cloneable接口并重寫Object類中的clone()方法;
?2). 實現Serializable接口,通過對象的序列化和反序列化實現克隆,可以實現真正的深度克隆,。
?63.深拷貝和淺拷貝區別是什么?
在有指針成員的情況下,淺拷貝只是將指針指向已存在的內存。即兩個對象的指針成員指向的是同一內存區域。深拷貝的做法是申請一個內存復制一份,并將新對象指針指向備份區。
安全性:淺拷貝如果修改了指針指向的內容,將對兩個對象都有影響。
六、Java Web
64.jsp 和 servlet 有什么區別?
?jsp 是 html 頁面中內嵌的 Java 代碼,側重頁面顯示;
Servlet 是 html 代碼和 Java 代碼分離,側重邏輯控制,mvc 設計思想中 jsp 位于視圖層,servlet 位于控制層Jsp 運行機制.
65.jsp 有哪些內置對象?作用分別是什么?
Page,pageContext,request,response,session,application,out,config,exception
?Page指的是JSP被翻譯成Servlet的對象的引用.
?pageContext對象可以用來獲得其他8個內置對象,還可以作為JSP的域范圍對象使用.pageContext中存的值是當前的頁面的作用范圍》
?request代表的是請求對象,可以用于獲得客戶機的信息,也可以作為域對象來使用,使用request保存的數據在一次請求范圍內有效。
Session代表的是一次會話,可以用于保存用戶的私有的信息,也可以作為域對象使用,使用session保存的數據在一次會話范圍有效
Application:代表整個應用范圍,使用這個對象保存的數據在整個web應用中都有效。
?Response是響應對象,代表的是從服務器向瀏覽器響應數據.
Out:JSPWriter是用于向頁面輸出內容的對象
Config:指的是ServletConfig用于JSP翻譯成Servlet后 獲得Servlet的配置的對象.
Exception:在頁面中設置isErrorPage=”true”,即可使用,是Throwable的引用.用來獲得頁面的錯誤信息。
66.說一下 jsp 的 4 種作用域?
67.session 和 cookie 有什么區別?
1.?Cookie以文本文件格式存儲在瀏覽器中,而session存儲在服務端它存儲了限制數據量。它只允許4kb它沒有在cookie中保存多個變量。
2.cookie的存儲限制了數據量,只允許4KB,而session是無限量的
3.我們可以輕松訪問cookie值但是我們無法輕松訪問會話值,因此它更安全
4.設置cookie時間可以使cookie過期。但是使用session-destory(),我們將會銷毀會話。
68.說一下 session 的工作原理?
整個流程大概分成這樣的幾步: 第一步將本地的cookie中的session標識和用戶名,密碼帶到后臺中
第二步后臺檢測有沒有對應的session標識,我們以php為例,那么就是檢測有沒有接收到對應的PHPSESSID
沒有的話直接生成一個新的session。
有的話,檢測對應的文件是否存在并且有效 失效的話,我們需要清除session然后生成新的session。不失效,使用當前的session
69.如果客戶端禁止 cookie 能實現 session 還能用嗎?
設置php.ini配置文件中的“session.use_trans_sid = 1”,或者編譯時打開打開了“--enable-trans-sid”選項,讓PHP自動跨頁傳遞Session ID。
手動通過URL傳值、隱藏表單傳遞Session ID。
用文件、數據庫等形式保存Session ID,在跨頁過程中手動調用。
70.spring mvc 和 struts 2的區別是什么?
1. 底層實現機制 struts2:filter springmvc:servlet
2. 運行效率 struts2:底層是Servlet,參數基于屬性封裝,如果配置單例,會出現線程安全問題,所以配置多例 springmvc:底層是Servlet,單例
3. 參數封裝 struts2:基于屬性封裝 springmvc:基于方法進行封裝
71.如何避免 sql 注入?
不要使用動態SQL
不要將敏感數據保留在純文本中
限制數據庫權限和特權
避免直接向用戶顯示數據庫錯誤
?對訪問數據庫的Web應用程序使用Web應用程序防火墻(WAF)
定期測試與數據庫交互的Web應用程序
將數據庫更新為最新的可用修補程序
72.什么是 XSS 攻擊,如何避免?
XSS攻擊又稱CSS,全稱Cross Site Script (跨站腳本攻擊),其原理是攻擊者向有XSS漏洞的網站中輸入惡意的 HTML 代碼,當用戶瀏覽該網站時,這段 HTML 代碼會自動執行,從而達到攻擊的目的。XSS 攻擊類似于 SQL 注入攻擊,SQL注入攻擊中以SQL語句作為用戶輸入,從而達到查詢/修改/刪除數據的目的,而在xss攻擊中,通過插入惡意腳本,實現對用戶游覽器的控制,獲取用戶的一些信息。 XSS是 Web 程序中常見的漏洞,XSS 屬于被動式且用于客戶端的攻擊方式。
?1.利用 php htmlentities()函數對傳入參數的非法的 HTML 代碼包括單雙引號等進行轉義。但是,中文情況下, htmlentities() 卻會轉化所有的 html 代碼,連同里面的它無法識別的中文字符也給轉化了。
2.利用 php htmlspecialchars()函數對傳入參數的非法的 HTML 代碼包括單雙引號等進行轉義,需要注意的是第二個參數默認是 ENT_COMPAT,函數默認只是轉化雙引號("),不對單引號(')做轉義。更多的時候要加上第二個參數,應該這樣用 : htmlspecialchars($string,ENT_QUOTES)對單雙引號都進行轉義。如果需要不轉化任何的引號第二個參數使用ENT_NOQUOTES。
?3.通過正則表達式過濾傳入參數的html標簽來防范XSS攻擊
73.什么是 CSRF 攻擊,如何避免?
CSRF(Cross-site request forgery)也被稱為 one-click attack或者 session riding,中文全稱是叫跨站請求偽造。一般來說,攻擊者通過偽造用戶的瀏覽器的請求,向訪問一個用戶自己曾經認證訪問過的網站發送出去,使目標網站接收并誤以為是用戶的真實操作而去執行命令。常用于盜取賬號、轉賬、發送虛假消息等。攻擊者利用網站對請求的驗證漏洞而實現這樣的攻擊行為,網站能夠確認請求來源于用戶的瀏覽器,卻不能驗證請求是否源于用戶的真實意愿下的操作行為。
1.驗證 HTTP Referer 字段
?2.使用驗證碼
3.在請求地址中添加token并驗證
4.在HTTP 頭中自定義屬性并驗證
5.AngularJS提供的CSRF方案
七、異常
74.throw 和 throws 的區別?
throws是用來聲明一個方法可能拋出的所有異常信息,throws是將異常聲明但是不處理,而是將異常往上傳,誰調用我就交給誰處理。而throw則是指拋出的一個具體的異常類型。
75.final、finally、finalize 有什么區別??
final是關鍵字,當final用于修飾類時,這個類不可以被繼承,所以自然也就不能是抽象類(abstract);當final修飾方法時,這個方法不能夠被重寫;當final修飾變量時,這個變量不能被修改。
?finally是異常處理的出口,在異常處理流程中,如果有了finally代碼塊,則程序不管是否被捕捉到異常或者異常是否被處理,都要執行finally代碼塊中的程序。
?finalize是方法名稱,是Object中的方法,這個方法在對象被垃圾回收集收集之前進行調用,可以在此進行一些擴展,如果調用這個方法時,拋出了無法補貨的異常,GC將終止對這個對象的回收,等到下次GC時再進行回收。
76.try-catch-finally 中哪個部分可以省略?
catch 和 finally 語句塊可以省略其中一個。
77.try-catch-finally 中,如果 catch 中 return 了,finally 還會執行嗎?
一定會, catch 中 return會等finally中的代碼執行完之后才會執行。
78.常見的異常類有哪些?
?NullPointerException 空指針異常
ClassNotFoundException 指定類不存在
?NumberFormatException 字符串轉換為數字異常
?IndexOutOfBoundsException 數組下標越界異常
ClassCastException 數據類型轉換異常
?FileNotFoundException 文件未找到異常
?NoSuchMethodException 方法不存在異常
?IOException IO 異常
SocketException Socket 異常
八、網絡
79.http 響應碼 301 和 302 代表的是什么?有什么區別?
?301表示網頁永久性轉移到另一個地址 302表示臨時性轉移
區別: 301是永久的重定向,搜索引擎在抓取新內容的同時也將舊的網址替換為重定向之后的網址 302重定向是臨時的重定向,搜索引擎抓取新的內容而保留舊的網址
?80.forward 和 redirect 的區別?
?forward 是服務器的內部重定向
redirect 是服務器收到請求后發送一個狀態頭給客戶,客戶將在重新請求一次
81.簡述 tcp 和 udp的區別?
?tcp 面向連接,udp 面向非連接即發送數據前不需要建立鏈接;
?tcp 提供可靠的服務(數據傳輸),udp 無法保證;
?tcp 面向字節流,udp 面向報文; tcp 數據傳輸慢,udp 數據傳輸快
82.tcp 為什么要三次握手,兩次不行嗎?為什么?
如果采用兩次握手,那么只要服務器發出確認數據包就會建立連接,但由于客戶端此時并未響應服務器端的請求,那此時服務器端就會一直在等待客戶端,這樣服務器端就白白浪費了一定的資源。若采用三次握手,服務器端沒有收到來自客戶端的再此確認,則就會知道客戶端并沒有要求建立請求,就不會浪費服務器的資源
83.說一下 tcp 粘包是怎么產生的?
tcp 粘包可能發生在發送端或者接收端,分別來看兩端各種產生粘包的原因:
?發送端粘包:發送端需要等緩沖區滿才發送出去,造成粘包;
接收方粘包:接收方不及時接收緩
84.OSI 的七層模型都有哪些?
物理層:利用傳輸介質為數據鏈路層提供物理連接,實現比特流的透明傳輸。
數據鏈路層:負責建立和管理節點間的鏈路。
網絡層:通過路由選擇算法,為報文或分組通過通信子網選擇最適當的路徑。
傳輸層:向用戶提供可靠的端到端的差錯和流量控制,保證報文的正確傳輸。
會話層:向兩個實體的表示層提供建立和使用連接的方法。
表示層:處理用戶信息的表示問題,如編碼、數據格式轉換和加密解密等。
應用層:直接向用戶提供服務,完成用戶希望在網絡上完成的各種工作。
85.get 和 post 請求有哪些區別?
get請求的參數在URL中,而post 請求在請求body中
get請求傳參有長度限制,post請求沒有長度限制
get請求的參數只能是ASCII碼,post請求傳參沒有這個限制沖區的包,造成多個包接收。
86.如何實現跨域?
使用CORS技術
使用JSONP
87.說一下 JSONP 實現原理?
?jsonp是一種輕量級的數據交換格式。
?jsonp:JSON with Padding,它是利用script標簽的 src 連接可以訪問不同源的特性,加載遠程返回的“JS 函數”來執行的。
九、設計模式
88.說一下你熟悉的設計模式?
單例模式:保證被創建一次,節省系統開銷。
工廠模式(簡單工廠、抽象工廠):解耦代碼。
觀察者模式:定義了對象之間的一對多的依賴,這樣一來,當一個對象改變時,它的所有的依賴者都會收到通知并自動更新。
外觀模式:提供一個統一的接口,用來訪問子系統中的一群接口,外觀定義了一個高層的接口,讓子系統更容易使用。
模版方法模式:定義了一個算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類可以在不改變算法結構的情況下,重新定義算法的步驟。
狀態模式:允許對象在內部狀態改變時改變它的行為,對象看起來好像修改了它的類。
89.簡單工廠和抽象工廠有什么區別?
簡單工廠:用來生產同一等級結構中的任意產品,對于增加新的產品,無能為力。
工廠方法:用來生產同一等級結構中的固定產品,支持增加任意產品。
抽象工廠:用來生產不同產品族的全部產品,對于增加新的產品,無能為力;支持增加產品族
十、Spring/Spring MVC
90.為什么要使用 spring?
spring是一個開源框架,是個輕量級的控制反轉(IoC)和面向切面(AOP)的容器框架
方便結構簡化開發
AOP編碼的支持
聲明式事物的支持
方便程序的測試
方便集成各種優勢框架
降低Java EE API 的使用難度
91.解釋一下什么是 aop?
AOP即面向切面編程,是OOP編程的有效補充。使用AOP技術,可以將一些系統性相關的編程工作,獨立提取出來,獨立實現,然后通過切面切入進系統。從而避免了在業務邏輯的代碼中混入很多的系統相關的邏輯——比如權限管理,事物管理,日志記錄等等。
AOP分為靜態AOP和動態AOP:
?靜態AOP是指AspectJ實現的AOP,他是將切面代碼直接編譯到Java類文件中。
?動態AOP是指將切面代碼進行動態織入實現的AOP,JDK動態代理。
?92.解釋一下什么是 ioc?
即“控制反轉”,不是什么技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。
?IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫對象找相應的依賴對象并注入,而不是由對象主動去找。
93.spring 有哪些主要模塊?
?spring core:框架的最基礎部分,提供 ioc 和依賴注入特性。
?spring context:構建于 core 封裝包基礎上的 context 封裝包,提供了一種框架式的對象訪問方法。
?spring dao:Data Access Object 提供了JDBC的抽象層。
spring aop:提供了面向切面的編程實現,讓你可以自定義攔截器、切點等。
?spring Web:提供了針對 Web 開發的集成特性,例如文件上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
?spring Web mvc:spring 中的 mvc 封裝包提供了 Web 應用的 Model-View-Controller(MVC)的實現。
94.spring 常用的注入方式有哪些?
構造方法注入
setter注入
基于注解注入
95.spring 中的 bean 是線程安全的嗎?
spring 中的 bean 默認是單例模式,spring 框架并沒有對單例 bean 進行多線程的封裝處理。 實際上大部分時候 spring bean 無狀態的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態的話(比如 view model 對象),那就要開發者自己去保證線程安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當于 new Bean()了,所以就可以保證線程安全了。
有狀態就是有數據存儲功能。
無狀態就是不會保存數據。
96.spring 支持幾種 bean 的作用域?
singleton、prototype、request、session、globalSession五中作用域。
singleton:spring ioc 容器中只存在一個 bean 實例,bean 以單例模式存在,是系統默認值;
prototype:每次從容器調用 bean 時都會創建一個新的示例,既每次 getBean()相當于執行 new Bean()操作;
Web 環境下的作用域: request:每次 http 請求都會創建一個 bean;
session:同一個 http session 共享一個 bean 實例;
?global-session:用于 portlet 容器,因為每個 portlet 有單獨的 session,globalsession 提供一個全局性的 http session
97.spring 自動裝配 bean 有哪些方式?
byName:按照bean的屬性名稱來匹配要裝配的bean
byType:按照bean的類型來匹配要裝配的bean
constructor:按照bean的構造器入參的類型來進行匹配
autodetect(自動檢測):先使用constructor進行裝配,如果不成功就使用byType來裝配
98.spring 事務實現方式有哪些?
聲明式事務:聲明式事務也有兩種實現方式,基于 xml 配置文件的方式和注解方式。
編碼方式:提供編碼的形式管理和維護事務。
99.說一下 spring 的事務隔離?
spring 有五大隔離級別,默認值為 ISOLATION_DEFAULT(使用數據庫的設置),其他四個隔離級別和數據庫的隔離級別一致:
?ISOLATION_DEFAULT:用底層數據庫的設置隔離級別,數據庫設置的是什么我就用什么;
ISOLATIONREADUNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、臟讀、不可重復讀);
?ISOLATIONREADCOMMITTED:提交讀,一個事務提交后才能被其他事務讀取到(會造成幻讀、不可重復讀),SQL server 的默認級別;
ISOLATIONREPEATABLEREAD:可重復讀,保證多次讀取同一個數據時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的數據(會造成幻讀),MySQL 的默認級別; ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復讀、幻讀。
臟讀 :表示一個事務能夠讀取另一個事務中還未提交的數據。比如,某個事務嘗試插入記錄 A,此時該事務還未提交,然后另一個事務嘗試讀取到了記錄 A。
?不可重復讀 :是指在一個事務內,多次讀同一數據。
幻讀 :指同一個事務內多次查詢返回的結果集不一樣。比如同一個事務 A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集里面的數據,同一個記錄的數據內容被修改了,所有數據行的記錄就變多或者變少了
100.說一下 spring mvc 運行流程?
?spring mvc 先將請求發送給 DispatcherServlet。
DispatcherServlet 查詢一個或多個 HandlerMapping,找到處理請求的 Controller。
DispatcherServlet 再把請求提交到對應的 Controller。
Controller 進行業務邏輯處理后,會返回一個ModelAndView。
?Dispathcher 查詢一個或多個 ViewResolver 視圖解析器,找到 ModelAndView 對象指定的視圖對象。 視圖對象負責渲染返回給客戶端
101.spring mvc 有哪些組件?
前置控制器 DispatcherServlet?
映射控制器 HandlerMapping
處理器 Controller
模型和視圖 ModelAndView
視圖解析器 ViewResolver
102.@RequestMapping 的作用是什么?
將 http 請求映射到相應的類/方法上
103.@Autowired 的作用是什么?
可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作,通過@Autowired 的使用來消除 set/get 方法
十一、Spring Boot/Spring Cloud
104.什么是 spring boot?
Spring Boot是一個構建在Spring框架頂部的項目。它提供了一種更簡單、更快捷的方法來設置、配置和運行簡單和基于Web的應用程序。
105.為什么要用 spring boot?
?配置簡單,獨立運行,自動裝配,無代碼生成和 xml 配置,提供應用監控,易上手,提升開發效率。
106.spring boot 核心配置文件是什么?
?bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加載的,比 applicaton 優先加載,且 boostrap 里面的屬性不能被覆蓋 application (. yml 或者 . properties):用于 spring boot 項目的自動化配置
107.spring boot 配置文件有哪幾種類型?它們有什么區別?
配置文件有 . properties 格式和 . yml 格式,它們主要的區別是書法風格不同。
. properties 配置如下:
?spring. RabbitMQ. port=5672
. yml 配置如下:
spring:
RabbitMQ:
?port: 5672
. yml 格式不支持 @PropertySource 注解導入
108.spring boot 有哪些方式可以實現熱部署?
使用 devtools 啟動熱部署,添加 devtools 庫,在配置文件中把 spring. devtools. restart. enabled 設置為 true
使用 Intellij Idea 編輯器,勾上自動編譯或手動重新編譯
109.jpa 和 hibernate 有什么區別?
?jpa 全稱 Java Persistence API,是 Java 持久化接口規范,hibernate 屬于 jpa 的具體實現。
?110.什么是 spring cloud?
spring cloud 是一系列框架的有序集合。它利用 spring boot 的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現注冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用 spring boot 的開發風格做到一鍵啟動和部署。
111.spring cloud 斷路器的作用是什么?
在分布式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間占用不釋放,避免了故障在分布式系統中的蔓延。
112.spring cloud 的核心組件有哪些?
Eureka:服務注冊于發現
?Feign:基于動態代理機制,根據注解和選擇的機器,拼接請求 url 地址,發起請求
Ribbon:實現負載均衡,從一個服務的多臺機器中選擇一臺
Hystrix:提供線程池,不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務雪崩的問題
Zuul:網關管理,由 Zuul 網關轉發請求給對應的服務
十二、Hibernate
113.為什么要使用 hibernate?
?hibernate 是對 jdbc 的封裝,大大簡化了數據訪問層的繁瑣的重復性代碼。
?hibernate 是一個優秀的 ORM 實現,很多程度上簡化了 DAO 層的編碼功能。
可以很方便的進行數據庫的移植工作。 提供了緩存機制,是程序執行更改的高效。
114.什么是 ORM 框架?
ORM(Object Relation Mapping)對象關系映射,是把數據庫中的關系數據映射成為程序中的對象。
使用 ORM 的優點:提高了開發效率降低了開發成本、開發更簡單更對象化、可移植更強。
115.hibernate 中如何在控制臺查看打印的 sql 語句?
?在 Config 里面把 hibernate. show_SQL 設置為 true 就可以。但不建議開啟,開啟之后會降低程序的運行效率。 116.hibernate 有幾種查詢方式? 三
種:hql、原生 SQL、條件查詢 Criteria。
116.hibernate 有幾種查詢方式?
三種:hql、原生 SQL、條件查詢 Criteria。
117.hibernate 實體類可以被定義為 final 嗎?
實體類可以定義為 final 類,但這樣的話就不能使用 hibernate 代理模式下的延遲關聯提供性能了,所以不建議定義實體類為 final。
118.在 hibernate 中使用 Integer 和 int 做映射有什么區別?
Integer 類型為對象,它的值允許為 null,而 int 屬于基礎數據類型,值不能為 null。
119.hibernate 是如何工作的?
讀取并解析配置文件。
?讀取并解析映射文件,創建 SessionFactory。
?打開 Session。
?創建事務。
?進行持久化操作。
提交事務。
關閉 Session。
關閉 SessionFactory。
120.get和 load的區別?
數據查詢時,沒有 OID 指定的對象,get() 返回 null;load() 返回一個代理對象。
?load()支持延遲加載;get() 不支持延遲加載。
121.說一下 hibernate 的緩存機制?
?hibernate 常用的緩存有一級緩存和二級緩存:
?一級緩存:也叫 Session 緩存,只在 Session 作用范圍內有效,不需要用戶干涉,由 hibernate 自身維護,可以通過:evict(object)清除 object 的緩存;clear()清除一級緩存中的所有緩存;flush()刷出緩存;
二級緩存:應用級別的緩存,在所有 Session 中都有效,支持配置第三方的緩存,如:EhCache。
122.hibernate 對象有哪些狀態?
臨時/瞬時狀態:直接 new 出來的對象,該對象還沒被持久化(沒保存在數據庫中),不受 Session 管理。 持久化狀態:當調用 Session 的 save/saveOrupdate/get/load/list 等方法的時候,對象就是持久化狀態。 游離狀態:Session 關閉之后對象就是游離狀態。
123.在 hibernate 中 getCurrentSession 和 openSession 的區別是什么?
getCurrentSession 會綁定當前線程,而 openSession 則不會。 getCurrentSession 事務是 Spring 控制的,并且不需要手動關閉,而 openSession 需要我們自己手動開啟和提交事務。
124.hibernate 實體類必須要有無參構造函數嗎?為什么?
hibernate 中每個實體類必須提供一個無參構造函數,因為 hibernate 框架要使用 reflection api,通過調用 ClassnewInstance() 來創建實體類的實例,如果沒有無參的構造函數就會拋出異常。
十三、Mybatis
125.mybatis 中 #{}和 ${}的區別是什么?
#{}是預編譯處理,${}是字符替換。 在使用 #{}時,MyBatis 會將 SQL 中的#{}替換成“?”,配合 PreparedStatement 的 set 方法賦值,這樣可以有效的防止 SQL 注入,保證程序的運行安全。
126. MyBatis 有幾種分頁方式?
分頁方式:邏輯分頁和物理分頁。
邏輯分頁: 使用 MyBatis 自帶的 RowBounds 進行分頁,它是一次性查詢很多數據,然后在數據中再進行檢索。
物理分頁: 自己手寫 SQL 分頁或使用分頁插件 PageHelper,去數據庫查詢指定條數的分頁數據的形式。
127. RowBounds 是一次性查詢全部結果嗎?為什么?
RowBounds 表面是在“所有”數據中檢索數據,其實并非是一次性查詢出所有數據,因為 MyBatis 是對 jdbc 的封裝,在 jdbc 驅動中有一個 Fetch Size 的配置,它規定了每次最多從數據庫查詢多少條數據,假如你要查詢更多數據,它會在你執行 next()的時候,去查詢更多的數據。就好比你去自動取款機取 10000 元,但取款機每次最多能取 2500 元,所以你要取 4 次才能把錢取完。只是對于 jdbc 來說,當你調用 next()的時候會自動幫你完成查詢工作。這樣做的好處可以有效的防止內存溢出。
128. MyBatis 邏輯分頁和物理分頁的區別是什么?
?邏輯分頁是一次性查詢很多數據,然后再在結果中檢索分頁的數據。這樣做弊端是需要消耗大量的內存、有內存溢出的風險、對數據庫壓力較大。 物理分頁是從數據庫查詢指定條數的數據,彌補了一次性全部查出的所有數據的種種缺點,比如需要大量的內存,對數據庫查詢壓力較大等問題。
129. MyBatis 是否支持延遲加載?延遲加載的原理是什么?
MyBatis 支持延遲加載,設置 lazyLoadingEnabled=true 即可。
?延遲加載的原理是調用的時候觸發加載,而不是在初始化的時候就加載信息。比如調用 a. getB(). getName(),這個時候發現 a. getB() 的值為 null,此時會單獨觸發事先保存好的關聯 B 對象的 SQL,先查詢出來 B,然后再調用 a. setB(b),而這時候再調用 a. getB(). getName() 就有值了,這就是延遲加載的基本原理。
?130. 說一下 MyBatis 的一級緩存和二級緩存?
一級緩存:基于 PerpetualCache 的 HashMap 本地緩存,它的聲明周期是和 SQLSession 一致的,有多個 SQLSession 或者分布式的環境中數據庫操作,可能會出現臟數據。當 Session flush 或 close 之后,該 Session 中的所有 Cache 就將清空,默認一級緩存是開啟的。
?二級緩存:也是基于 PerpetualCache 的 HashMap 本地緩存,不同在于其存儲作用域為 Mapper 級別的,如果多個SQLSession之間需要共享緩存,則需要使用到二級緩存,并且二級緩存可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啟二級緩存,使用二級緩存屬性類需要實現 Serializable 序列化接口(可用來保存對象的狀態)。 開啟二級緩存數據查詢流程:二級緩存 -> 一級緩存 -> 數據庫。 緩存更新機制:當某一個作用域(一級緩存 Session/二級緩存 Mapper)進行了C/U/D 操作后,默認該作用域下所有 select 中的緩存將被 clear。
131. MyBatis 和 hibernate 的區別有哪些?
靈活性:MyBatis 更加靈活,自己可以寫 SQL 語句,使用起來比較方便。 可
移植性:MyBatis 有很多自己寫的 SQL,因為每個數據庫的 SQL 可以不相同,所以可移植性比較差。
學習和使用門檻:MyBatis 入門比較簡單,使用門檻也更低。
二級緩存:hibernate 擁有更好的二級緩存,它的二級緩存可以自行更換為第三方的二級緩存。
132. MyBatis 有哪些執行器(Executor)?
?MyBatis 有三種基本的Executor執行器:
SimpleExecutor:每執行一次 update 或 select 就開啟一個 Statement 對象,用完立刻關閉 Statement 對象;
ReuseExecutor:執行 update 或 select,以 SQL 作為 key 查找 Statement 對象,存在就使用,不存在就創建,用完后不關閉 Statement 對象,而是放置于 Map 內供下一次使用。簡言之,就是重復使用 Statement 對象;
?BatchExecutor:執行 update(沒有 select,jdbc 批處理不支持 select),將所有 SQL 都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個 Statement 對象,每個 Statement 對象都是 addBatch()完畢后,等待逐一執行 executeBatch()批處理,與 jdbc 批處理相同。
133. MyBatis 分頁插件的實現原理是什么?
分頁插件的基本原理是使用 MyBatis 提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的 SQL,然后重寫 SQL,根據 dialect 方言,添加對應的物理分頁語句和物理分頁參數。 史上最全的Java面試題總匯,成功坐等offer(答案版)中
134. MyBatis 如何編寫一個自定義插件?
自定義插件實現原理 MyBatis
自定義插件針對 MyBatis 四大對象(Executor、StatementHandler、ParameterHandler、ResultSetHandler)進行攔截:
?Executor:攔截內部執行器,它負責調用 StatementHandler 操作數據庫,并把結果集通過 ResultSetHandler 進行自動映射,另外它還處理了二級緩存的操作;
?StatementHandler:攔截 SQL 語法構建的處理,它是 MyBatis 直接和數據庫執行 SQL 腳本的對象,另外它也實現了 MyBatis 的一級緩存;
?ParameterHandler:攔截參數的處理;
?ResultSetHandler:攔截結果集的處理。
?自定義插件實現關鍵 MyBatis 插件要實現 Interceptor 接口,接口包含的方法,如下:
?public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
setProperties 方法是在 MyBatis 進行配置插件的時候可以配置自定義相關屬性,即:接口實現對象的參數配置;
?plugin 方法是插件用于封裝目標對象的,通過該方法我們可以返回目標對象本身,也可以返回一個它的代理,可以決定是否要進行攔截進而決定要返回一個什么樣的目標對象,官方提供了示例:return Plugin. wrap(target, this);
?intercept 方法就是要進行攔截的時候要執行的方法。 自定義插件實現示例 官方插件實現:
@Intercepts({@Signature(type = Executor. class, method = "query",
args = {MappedStatement. class, Object. class, RowBounds. class, ResultHandler. class})})public class TestInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation. getTarget(); //被代理對象
?Method method = invocation. getMethod(); //代理方法
Object[] args = invocation. getArgs(); //方法參數
?// do something . . . . . . 方法攔截前執行代碼塊
?Object result = invocation. proceed();
// do something . . . . . . . 方法攔截后執行代碼塊
return result;
?}
public Object plugin(Object target) {
return Plugin. wrap(target, this);
?}
?}
剩余的部分在下文中哦,敬請期待。請關注小編