什麼是ORM? (建議學習:java訪談題目)
#物件關係對應(Object-Relational Mapping,簡稱ORM)是一種為了解決程式的物件導向模型與資料庫關係式的關聯式模型互不匹配問題的技術;
簡單的說,ORM是透過使用描述物件和資料庫之間映射的元資料(在Java中可以用XML或註解),將程式中的物件自動持久化到關聯式資料庫中或將關聯式資料庫表中的行轉換成Java對象,其本質上就是將資料從一種形式轉換到另外一種形式。
Hibernate中SessionFactory是執行緒安全的嗎? Session是線程安全的嗎(兩個線程能夠共享同一個Session嗎)?
SessionFactory對應Hibernate的一個資料儲存的概念,它是執行緒安全的,可以被多個執行緒並發存取。 SessionFactory一般只會在啟動的時候建置。對於應用程序,最好將SessionFactory透過單例模式進行封裝以便於存取。
Session是一個輕量級非執行緒安全的物件(執行緒間不能共享session),它表示與資料庫互動的一個工作單元。 Session是由SessionFactory創建的,在任務完成之後它會關閉。 Session是持久層服務對外提供的主要介面。
Session會延遲取得資料庫連線(也就是在需要的時候才會取得)。為了避免創建太多的session,可以使用ThreadLocal將session和當前線程綁定在一起,這樣可以讓同一個線程獲得的總是同一個session。
Hibernate 3中SessionFactory的getCurrentSession()方法就可以做到。
Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分別是做什麼的?有什麼區別?
Hibernate的物件有三種狀態:瞬時態(transient)、持久態(persistent)和遊離態(detached)。
瞬時態的實例可以透過呼叫save()、persist()或saveOrUpdate()方法變成持久性;
遊離態的實例可以透過呼叫update()、saveOrUpdate()、 lock()或replicate()變成持久態。 save()和persist()將會引發SQL的INSERT語句,而update()或merge()會引發UPDATE語句。
save()和update()的差別在於一個是將瞬時態物件變成持久態,一個是將遊離態物件變成持久態。 merge()方法可以完成save()和update()方法的功能,它的意圖是將新的狀態合併到現有的持久化物件上或建立新的持久化物件。
對於persist()方法,依照官方文件的說明:
#1、persist()方法把一個瞬時態的實例持久化,但並不保證標識符立刻被填入到持久化實例中,標識符的填入可能被推遲到flush的時間;
2、persist()方法保證當它在一個事務外部被調用的時候並不觸發一個INSERT語句,當需要封裝一個長會話流程的時候,persist()方法是很有必要的;
3、save()方法不保證第2條,它要回傳標識符,所以它會立即執行INSERT語句,不管是在事務內部或外部。
至於lock()方法和update()方法的區別,update()方法是把一個已經更改過的脫管狀態的物件變成持久狀態;lock()方法是把一個沒有更改過的脫管狀態的物件變成持久狀態。
闡述Session載入實體物件的過程。
1、Session在呼叫資料庫查詢功能之前,首先會在一級快取中透過實體類型和主鍵進行查找,如果一級快取查找命中且資料狀態合法,則直接返回;
2、如果一級快取沒有命中,接下來Session會在目前NonExists記錄(相當於一個查詢黑名單,如果出現重複的無效查詢可以迅速做出判斷,從而提升效能)中進行查找,如果NonExists中存在同樣的查詢條件,則傳回null;
3、如果一級快取查詢失敗查詢二級緩存,如果二級快取命中直接回傳;
4、如果之前的查詢都未命中,則發出SQL語句,如果查詢未發現對應記錄則將此次查詢添加到Session的NonExists中加以記錄,並返回null;
5、根據映射配置和SQL語句得到ResultSet,並建立對應的實體物件;
6、將物件納入Session(一級快取)的管理;
7、如果有對應的攔截器,則執行攔截器的onLoad方法;
8、如果開啟並設定了要使用二級緩存,則將資料物件納入二級緩存;
9、傳回資料物件。
#將傳入的資料都當成字串,會對傳入的資料自動加上引號;
$將傳入的資料直接顯示產生在SQL中。
注意:使用$佔位符可能會導致SQL注射攻擊,能用#的地方就不要使用$,寫order by子句的時候應該用$而不是#。
說明MyBatis中命名空間(namespace)的作用。
在大型專案中,可能存在大量的SQL語句,這時候為每個SQL語句起一個唯一的識別(ID)就變得不容易了。
為了解決這個問題,在MyBatis中,可以為每個映射檔案起一個唯一的命名空間,這樣定義在這個映射檔案中的每個SQL語句就成了定義在這個命名空間中的一個ID。
只要我們能夠保證每個命名空間中這個ID是唯一的,即使在不同映射檔案中的語句ID相同,也不會再產生衝突了。
MyBatis中的動態SQL是什麼意思?
對於一些複雜的查詢,我們可能會指定多個查詢條件,但是這些條件可能存在也可能不存在,如果不使用持久層框架我們可能需要自己拼裝SQL語句,不過MyBatis提供了動態SQL的功能來解決這個問題。 MyBatis中用來實作動態SQL的元素主要有:
- if - choose / when / otherwise - trim - where - set - foreach
用法範例:
<select id="foo" parameterType="Blog" resultType="Blog"> select * from t_blog where 1 = 1 <if test="title != null"> and title = #{title} </if> <if test="content != null"> and content = #{content} </if> <if test="owner != null"> and owner = #{owner} </if> </select>
##JDBC程式設計有哪些不足之處,MyBatis是如何解決這些問題的?
1、JDBC:資料庫連結建立、釋放頻繁造成系統資源浪費進而影響系統效能,如果使用資料庫連結池可解決此問題。 MyBatis:在SqlMapConfig.xml中設定資料連結池,使用連接池管理資料庫連結。 2、JDBC:Sql語句寫在程式碼中造成程式碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java程式碼。 MyBatis:將Sql語句配置在XXXXmapper.xml檔案中與java程式碼分開。 3、JDBC:向sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,佔位符需要和參數一一對應。 MyBatis: Mybatis自動將java物件對應至sql語句。 4,JDBC:對結果集解析麻煩,sql變化導致解析程式碼變化,解析前需要遍歷,如果能將資料庫記錄封裝成pojo物件解析比較方便。 MyBatis:Mybatis自動將sql執行結果對應至java物件。MyBatis與Hibernate有哪些不同?
1、Mybatis和hibernate不同,它不完全是一個ORM框架,因為MyBatis需要程式設計師自己寫Sql語句,不過mybatis可以透過XML或註解方式靈活配置要運行的sql語句,並將java物件和sql語句映射產生最終執行的sql,最後將sql執行的結果再映射產生java物件。 2、Mybatis學習門檻低,簡單易學,程式設計師直接編寫原始生態sql,可嚴格控制sql執行效能,靈活度高,非常適合對關聯式資料模型要求不高的軟體開發,例如互聯網軟體、企業營運軟體等,因為這類軟體需求變化頻繁,一但需求變化要求成果輸出迅速。 但是靈活的前提是mybatis無法做到資料庫無關性,如果需要實作支援多種資料庫的軟體則需要自訂多套sql映射文件,工作量大。 3、Hibernate物件/關係映射能力強,資料庫無關性好,對於關係模型要求高的軟體(例如需求固定的客製化軟體)如果用hibernate開發可以節省很多程式碼,提高效率。 但是Hibernate的缺點是學習門檻高,要精通門檻更高,而且怎麼設計O/R映射,在性能和對像模型之間如何權衡,以及怎樣用好Hibernate需要具有很強的經驗和能力才行。 總之,依照使用者的需求在有限的資源環境下只要能做出維護性、可擴展性良好的軟體架構就是好架構,所以架構只有適合才是最好。 (這裡也可以結合自己的理解說,別說的收不住)#簡單的說一下MyBatis的一級快取和二級快取?
Mybatis先到快取中查詢結果集,如果沒有則查詢資料庫,如果有則從快取取出回傳結果集就不走資料庫。 Mybatis內部儲存快取使用一個HashMap,key為hashCode sqlId Sql語句。 value為從查詢出來映射生成的java物件Mybatis的二級快取即查詢緩存,它的作用域是一個mapper的namespace,即在同一個namespace中查詢sql可以從快取中獲取資料。二級緩存是可以跨SqlSession的。以上是Java持久層面試題目的詳細內容。更多資訊請關注PHP中文網其他相關文章!