1. 程式人生 > >hibernate 面試題

hibernate 面試題

1 講講一下orm框架 以及各個orm框架的區別
答:o---Object物件。
r---關係資料庫。
m---對映檔案。
orm可以說是一項為了實現面向物件與關係資料庫的不匹配而產生的一種框架,簡單的說:orm是通過使用描述物件與關係資料庫之間對映的元資料,
將Java程式中的物件通過自動持久化同步到關係資料庫,本質上來說就是把資料從一種形式轉換成另一種形式。
orm型別 對映關係 開發效率 資料庫移植
hibernate: 全自動 實體類和資料庫 自動生成sql 不同資料庫型別的支援
ibatis: 半自動 實體類和SQL語句 需要編寫具體的sql 標準SQL方便移植
2 hibernate 的原理及其步驟
答:1.
讀取配置(Configuration)*.cfg.xml。 2.使用Configuration建立SessionFactory(執行緒安全)。 3.使用SessionFactory建立Session(執行緒不安全,使用本地執行緒TheradLocal解決)。 SessionFactory提供了兩種方式得到session。 1 openSession:得到的session是執行緒不安全的,可以通過本地執行緒 Threadlocal機制解決,把session放入Threadlocal中, 達到隔離執行緒的目的,得到的session需要手動關閉。 2 getCurrentSession可以解決要在事務範圍內 session 執行緒不安全問題,因為它總是把session繫結到當前執行緒, 並且在事務提交的時候自動關閉session。 但需要配置:<property
name="hibernate.current_session_context_class">thread</property><!--針對jdbc的--> 自動關閉session 4.利用Session啟動事務(Transaction)。 5.利用Session進行業務操作。 6.提交事務(呼叫commit()方法)。 7.關閉Session(呼叫close()方法)。 3 說出Hibernate的核心類和介面: 答: Configuration:管理從配置檔案(*.cfg.xml)中讀取的資訊。 SessionFactory:根據配置資訊建立一個SessionFactory例項。 Session:持久化方法是通過Session來完成的。 Transaction: 事務管理。 Query:查詢介面。 SQLQuerry:sql查詢的查詢介面。 4
hibernate 實體的3種狀態 答: 1.瞬時狀態:這種狀態一般都是剛new出來,這種狀態下的資料還沒有與session有關聯不能與資料庫同步。 2.持久化狀態:當資料與session產生關聯後就由瞬時狀態轉變為持久化狀態,只有與session產生關聯後資料才能同步到資料庫。 3.離線狀態:這種狀態曾經被持久化過,而且資料庫中也與之有關聯,但是當前session已經關閉,與Session已經沒有任何的關聯, 資料庫中同步的資料是在Session關閉之前最後一次提供的資料,當session關閉之後資料就不能同步到資料庫了。 幾種狀態之間是可以互相轉換的:瞬時狀態可以通過session進入持久化狀態,持久化狀態通過關閉Session進入離線狀態, 而離線狀態可以通過update或saveUpdate等方法回到持久化狀態,可以通過Delete回到瞬時狀態。 5 hibernate的幾種查詢方式 hibernate的sql查詢介面是什麼 答: 1.hql查詢:hql是面向物件而不是面向資料庫的查詢,Query作為hql的查詢介面,Query通過Session建立查詢語句(查詢語句的原來是表名, 現在是屬性類名,原來是欄位,現在是屬性)通過session呼叫createQuery方法實現語句查詢。 hql支援兩種查詢方式:佔位符(問號)與命名引數(冒號),不支援*操作,不適合動態查詢。 2.sql查詢:SQLQuery就是sql的查詢介面,此時查詢就是sql語句表名就是表名欄位名就是欄位名,預設查詢出來的list不是屬性類物件, 而是Object陣列,可以通過SQLQuerry.addEntity(屬性類.class)進行轉換。 也支援命名引數與佔位符,但是它的移植性差。 3.qbc查詢:Criteria是qbc的查詢介面,這種查詢方式不需要sql語句也不需要hql查詢方法,不過對於太複雜的查詢還是不建議使用, 通過Criteria使用Session創建出來的例項.add(Restrictions.eq("欄位",條件))來進行條件查詢。 4.qbe查詢:通過使用樣板來查詢資料庫中的記錄,給出要查詢記錄的所有欄位條件,如果不給出查詢條件那麼此時從屬性類中拿出來的屬性 都是等於null或0,因此查不出任何記錄。 6 什麼是hibernate主鍵生成機制 舉例說明 答: 主鍵生成機制就是通過在*.hbm.xml檔案中generator標籤裡進行配置,通過使用不同的主鍵機制而產生不同的主鍵效能。 如:assigned,主鍵的生成值完全由使用者決定,與底層資料庫無關。使用者需要維護主鍵值,在呼叫session.save()之前要指定主鍵值。 hilo 會多生成一個表,使用高低位演算法生成主鍵。 increment(英撲來慢特),由hibernate管理主鍵,自動以遞增的方式生成欄位值,每次增量為1,該主鍵必須為Integer型別。 identity(安踢踢),由資料庫生成識別符號,identity是由資料庫自己生成的,但這個主鍵必須設定為自動增長,前提條件是資料庫支援自動增長欄位型別, 有可能增長的幅度不一定為1。 uuid,資料類為String型別,由 Hibernate 通過128位uuid演算法生成16進位制數值(編碼後以長度32的字串表示)作為主鍵。 sequence(賽寬絲) 採用資料庫提供的 sequence(序列) 機制生成主鍵。如 Oralce 中的Sequence。 foreign 使用另外一個相關聯的物件的識別符號作為主鍵。 native 由Hibernate根據使用的資料庫自行判斷採用 identity、hilo、sequence 其中一種作為主鍵生成方式。 7 闡述一下hibernate的對映 在關聯對映中一對多 和 多對多 是如何實現的 要注意什麼問題? 答: 對映分為四種: 1 基本型別的對映。 2 集合對映:加一個表,主鍵關聯起來,1 list對映 有序可重複,2 set 無序不可重複,3 bag 無序可重複,4 map對映。 3 級聯對映:1 一對一,2 一對多,3 多對多 分為單向對映(一方持有另一方的實體或集合),雙向對映(彼此持有對方的實體或集合)。 1. 一對一:1 外來鍵關聯,把外來鍵對應的欄位加上唯一約束。 2 主鍵關聯,雙方共用一個主鍵,採用的主鍵生產機制是foreign。 2. 一對多:使用的是級聯與反轉。 1. 一般使用的是雙向關聯,在一方放多方的集合,在多方放一方的實體。 2. 反轉:1. 如果不用反轉 hibernate預設由一方維護關聯關係的欄位,做法是一個一個的對集合裡面的資料進行插入, 關聯欄位為空,之後發一條一條的uodate語句去更新關聯欄位。 2. 如果用反轉 表明將關聯關係維護權交給另一方(多方)管理,由多方維護關聯欄位的話,不會產生update語句, 帶來了效能上的提升。 3. 使用反轉:在one-to-many或many-to-many的集合定義中使用,inverse=“true”表示該物件不維護關聯關係, 該屬性的值一般在使用有序集合時設定成false(注意hibernate的預設值是false), one-to-many維護關聯關係就是更新外來鍵,many-to-many維護關聯關係就是在中間表增減記錄。 3. 級聯:當主物件做操作時候其關聯的物件也做與主物件類似的操作,可以減少程式碼,一般在一方使用, 因為如果在多方使用的話那就沒什麼意義了。 注意:級聯時給關聯物件設定id時需要注意,hibernate會對關聯的物件進行修改,如果關聯物件在資料庫不存在的時候會報錯。 使用級聯刪除時需要關聯物件持久化,否則報外來鍵約束錯誤。 3. 多對多:加一箇中間表,many-to-many,實則是轉成兩個一對多,而中間表是放了雙方的id作為聯合主鍵,和約束。 使用雙向多對多的時候,使他們同時指向一個表,不能會建立兩個中間表出來,但只有一箇中間表會儲存到資料, 並且要指明關聯欄位維護權的問題,一個使用inverse="false" 一個使用inverse="true",否則會出現主鍵重複的問題。 4 繼承對映:1 每個類一張表,2 每個子類一張表,父類沒有表,3 所有類一張表 5 元件對映:它只是一個普通的java類,沒有對映檔案,但是它不是hibernate的實體,而是實體的一部分,將可重用的部分提取出來, 使它可以進行重用。 8 hibernate的快取是什麼 用來幹什麼的 什麼時候用什麼方法重新整理快取 各種快取裡放的是什麼東西 使用快取應該注意什麼 答: 1. 快取是什麼:快取是介於物理資料來源與應用程式之間,是資料庫資料在記憶體中的存放臨時copy的容器, 其作用是為了減少應用程式對物理資料來源訪問的次數,從而提高了應用的執行效能。 2. 使用快取的條件。 1.讀取大於修改。 2.資料量不能超過記憶體容量。 3.可以容忍出現無效資料。 3. 一級快取,是session共享級別的,hibernate內建的快取,裡面存放的實體,因為它是hibernate內建的快取不能控制快取的數量, 所以要注意大批量操作資料時可能造成記憶體溢位,可以用clear方法清除快取中的內容。 4. 二級快取,SessionFactory級共享,是放在配置檔案中,實現為可插拔,裡面存放實體。 1 如果使用二級快取就需要在配置檔案中配置開發二級快取,使用evict(屬性類.class)方法清除二級快取。 2 開啟二級快取的步驟:二級快取的配置和使用。 * 開啟二級快取,修改hibernate.cfg.xml檔案 在hibernate的配置檔案中使用property屬性開啟。 <property name="hibernate.cache.use_second_level_cache">true</property> * 指定快取產品提供商,修改hibernate.cfg.xml檔案 指定快取產品的提供商(EhCache(衣艾去k其)),也是在配置檔案中用property屬性指定。 <property ame="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> * 指定那些實體類使用二級快取(兩種方法) * 在對映檔案中採用<cache>標籤 <cache usage="read-only"/> usage="read-only"是“只讀”快取策略,這個<cache>標籤只能放在<class>標籤的內部,而且必須處在<id>標籤的前面。 * 在hibernate.cfg.xml配置檔案中,採用<class-cache>標籤。 <class-cache class="com.lxit.hibernate.Classes" usage="read-only"/> 注意:這個<class-cache>標籤必須放在<mapping>標籤的後面。 5. 查詢快取,Query,Criteria(查詢快取)由於命中率較低,所以hibernate預設是關閉的。 1 在配置檔案中使用property屬性開啟查詢快取開關。<property name="hibernate.cache.use_query_cache">true</property> 2 在程式中手動啟用查詢快取query.setCacheable(true)或criteria.setCacheable(true),是先讀取查詢快取,再把讀出來的資料放入查詢快取中。 SessionFactory中提供了evictQueries()方法用來清除快取中的內容。 3 如果查詢的是實體放入的是id,否則就放入整個結果集。 4 查詢快取裡面放的是: 1 查詢的list裡面放的是實體,會把實體放入的一級快取與二級快取裡面,則查詢快取裡面放的是id, 會根據id到一級快取與二級快取裡面去找相對於的資料,找不到會發sql到資料庫中找。 2 如果查詢的list裡面放的不是實體,只是查某些欄位,查詢快取裡面放的是查詢的結果集。 6. 使用快取應該注意什麼: 1 使用快取時應該用於的系統是查詢大於修改,因為查詢出來的資料會放入快取中下次直接從快取中拿出來,不用資料庫發sql進行查詢, 這樣大大提升了系統的效能,而修改過多每次查詢都是不同的資料,每次都要重新到資料庫中拿值,這樣就降低了專案的效能。 2 資料量不能超過記憶體容量,否則會報系統記憶體溢位錯誤。 3. 使用一級快取的問題,當Session關閉后里面的資料就沒有了,因為不能控制,所以要注意大批量操作資料時可能造成記憶體溢位。 4. 使用二級快取的問題,要注意它的命中率,如果命中率太低對系統性能的消耗會很大。 7. 檢視二級快取的命中率: (1) 在hibernate的配置檔案中要開啟命中率開關,<property name="hibernate.generate_statistics">true</property>。 (2) 通過sessionFactory.getStatistics().getSecondLevelCacheHitCount();,檢視命中的次數(是從二級快取中查詢出來的)。 通過sessionFactory.getStatistics().getSecondLevelCacheMissCount());,檢視沒有命中的次數。 9 load與get save與persist saveorupdate與merge list與iterator 區別 答:它們的是把資料放入快取中的。 1 load(漏斗)(支援懶載入)根據id在查詢時不會立即訪問資料庫,而是在需要使用時才會訪問資料庫,如果id不存在會報找不到id錯誤。 get(不支援懶載入)根據id查詢時會立即訪問資料庫,如果id不存在則返回null。 2 save(賽屋)儲存資料登記相應的動作到對列中,並把實體放入session中,等待flush方法呼叫同步資料庫。 persist(炮賽絲特)在事務外不會產生增加語句 ,在主鍵生成機制是native中可以看到。 3 merge(冒傑) 呼叫merge物件就不會變成持久化狀態的,當id在快取中存在對應的實體時,就是把兩個合併。 saveOrUpdate碰到這種情況會報錯,因為相同的主鍵在session中已經存在另一個object。 4 list它是一次性把所有的資料查詢出來,而且會把查詢出來的資料放入一級快取中,也會放入二級快取,會把讀出來的資料放入查詢快取中, 但是不使用一級快取,同樣也不使用二級快取,list會使用查詢快取。 iterator不會把查詢出來的資料放入一級快取中,也不會放入二級快取,但是使用一級快取,同樣會使用二級快取,不使用查詢快取, 因為迭代器會先到資料庫中把id都取出來,然後真正要遍歷某個物件的時候先到快取中找,如果找不到,以id為條件再發一條sql到資料庫, 這樣如果快取中沒有資料,則查詢資料庫的次數為n+1。 專案中用list與iterator:先使用list查詢,因為它會把查詢出來的資料放入快取中,然後使用iterator,它會去快取中查詢資料。 10 什麼是懶載入(延遲載入) 懶載入用什麼技術實現 如何解決session關閉導致的懶載入問題 解決的方案有缺點嗎 答: 懶載入:1. 當具體確定用到某個資料時才會去載入資料庫,跟我們以前講的JVM的類裝載器差不多,用誰載入誰。 2. 懶載入使用的是代理技術來完成的,代理類就是載入物件的子類(系統定義的),如果把載入物件設定成final修飾那麼就不能使用懶載入。 3. 當Session關閉時會造成懶載入的問題,可以使用OpenSessionInView模式來完成懶載入問題,通過過濾器來實現, 在最開始訪問過濾器時就把Session開啟,直到執行完所有命令返回結果後關閉Session,這樣就不會出現懶載入問題。 4. 同樣這種方式也帶來了問題,事務擴大了,導致資源等待時間過長,session範圍變大,如果載入頁面的時間過長, 如網速比較慢,記憶體時間過長,導致系統性能下降,資料庫連線不能及時釋放。 概念:1 lazy的概念,指在需要資料的時候才發出sql。 2 lazy策略只是在session開啟期間才是有效的。 3 Hibernate載入本身就是延遲載入,在*.hbm.xml配置檔案中<class>裡配置lazy="false"將其改為非延遲載入。 4 Hibernate屬性的延遲載入,在*.hnm.xml配置檔案中<property>裡配置lazy="false"即可。 5 類的延遲載入並不影響屬性的延遲載入。 6 連線抓取會使lazy失效。 11 講講一下hibernate的抓取策略 答: hibernate的抓取分為:抓取策略就是抓與當前物件有關聯的實體或集合。 連線抓取 fetch="join":通過select語句使用外連線來載入其關聯實體或集合。? 查詢抓取 fetch="select":在查詢當前班級表後會另外發送一條select語句抓取當前物件關聯實體或集合。 子查詢抓取 fetch="subselect":另外發送一條select語句抓取在前面查詢到的所有實體物件的關聯實體或集合,通過子查詢in完成 批量抓取(batch-size="數量"):給的數量是多少就一次抓取多少條記錄(前提是資料庫中有那麼多記錄)。 12 hibernate如何處理大資料量? 答: 1.使用迴圈方法進行小量同步來清除快取,當迴圈方法載入完指定的數量後就呼叫flush把資料同步到資料庫,然後呼叫clear清除快取。 2.用(無狀態Session)StatelessSession介面:它不和一級快取、二級快取互動,也不觸發任何事件、監聽器、攔截器, 通過該介面的操作會立刻傳送給資料庫,與JDBC的功能一樣。 3.使用Query呼叫executeUpdate()執行批量更新,會清除相關聯的類二級快取,也可能會造成級聯,和樂觀鎖出現問題。 4.使用分頁機制,setFirstResult(2)表示從第3條記錄開始。setMaxResults(10)取10條記錄。 13 什麼是樂觀鎖與悲觀鎖? 答: 樂觀鎖:在資料庫中加一個version(版本號),欄位屬性為int,在讀取資料時把版本號一同讀出,在更新資料後資料庫自動為版本號加1, 如果在更新過程中出現什麼情況而沒有及時提交,而此時另一個人對此資料進行了更新,更新完後版本號自動加1, 此時資料庫中的版本號已經比之前讀出的版本號大1,如果提交的版本號小於或等於資料庫中的版本號那麼就會報當前資料已過期。 * 為什麼等於也過期呢? * 因為提交時版本號會自動加1後再去與資料庫中的版本號做比較。 悲觀鎖:鎖住之後在沒有提交之前任何人都改變不了原資料,但是有一個問題:在提交之後, 之前沒提交時別人修改過但是沒有修改成功的資料就會修改成功,使用LockMode.UPGRADE完成。 14 你是如何進行Hibernate的效能優化的 答: 在使用查詢資料時第一次使用list方法查詢,以後使用迭代方式查詢,因為list查詢它只會把資料放入快取中而不會使用快取, 迭代器查詢出的資料它不會放入快取但是會使用快取,有一點注意,迭代器不使用查詢快取,list會使用查詢快取。 處理大資料量時使用優化方法(請看第12題的優化方式)。 使用懶載入,關聯資料,主鍵生成機制也是對系統的一種優化。 根據命中率使用快取,命中率過底部建議使用快取。 在頁面顯示時如果有視訊就儘量使用懶載入。 關聯時使用雙向雙向對映。 15 講講hibernate的監聽器 它有什麼作用 細說一下hibernate儲存資料的步驟? 答: 1. hibernate的資料儲存是通過快取來實現的,通過Configuration載入配置檔案來建立SessionFactory,SessionFactory是執行緒安全的, 使用SessionFactory建立Session,建立Session有兩種方式,使用openSession得到的Session是執行緒不安全的,可以通過本地執行緒解決這個問題, 需要手動關閉Session,還可以使用getCurrentSession得到的Session是執行緒安全的,它是自動關閉Session,通過Session呼叫save或saveOrUpdate方法, 呼叫方法時會觸發一個事件,事件會通知監聽器,觸發監聽器裡的方法,然後把物件放進快取登入動作,等待flush(福拉西)重新整理, 提交事務,從快取中獲取資料同步到資料庫,一般是指定字串id。 呼叫兩次flush是否會發兩條sql,不會,因為它第一次會發送sql,但是它會登記的動作清除掉,flush是根據登記的動作傳送sql的。 2. 自定義監聽器 1 實現監聽器介面 如:SaveOrUpdateEventListener 重寫onSaveOrUpdate方法。 2 註冊監聽器 兩種形式: 1 在hibernate的xml裡面根據方法配置。 2 通過程式設計式,可以多個監聽器型別之間共享監聽器的例項,配置的每次都會產生一個新例項。 hibernate儲存資料:呼叫save方法把物件放進快取登入動作,等待flush(福拉西)重新整理,提交事務,從快取中獲取資料同步到資料庫。 16 spring是如何整合hibernate的 答: 1 用spring提供的LocalSessionFactoryBean,建立Sessionfactory, 注入資料來源dataSource,hibernate屬性hibernateProperties和對映檔案。 2 給HibernateTemplate類注入sessionFactory的例項,之後就可以用HibernateTemplate類封裝的hibernate的api操作。 3 繼承 HibernateDaoSupport類使程式碼更加簡潔,給HibernateTemplate類注入sessionFactory, 之後就可以用它的getHibernateTemplate方法獲得模板類。 4 事務整合,採用hibernate的事務管理器。 17 你有什麼hibernate的最佳實踐嗎 18 什麼是離線查詢 答:組裝sql時需要Session,查詢時不需要Session這是離線查詢。 離線查詢利用DetachedCriteria類使你在一個session範圍之外建立一個查詢,並且可以使用任意的Session來執行它,用在動態sql的構建上。 簡單說明:就是在Session的範圍之外建立查詢方式。 19 hibernate查詢單條記錄有幾種方法 答: 唯一記錄使用Session呼叫uinqueResult方法,當你確定本次查詢只有一條記錄可以用uinqueResult返回一個實體物件。 get方法 load方法。 20 你做專案為什麼使用hibernate 為什麼不使用hibernate 答:文件齊全,全自動的操作,自動生成sql等功能。 使用hibernate有幾方面的好處,它的快取機制可以為系統查詢時節省資源,主鍵機制,自動生成sql等效能比較強,使用比較靈活, 而且hibernate還可以在不同資料庫型別的支援,跨資料庫的功能,與底層資料庫分離,可移植。 不使用hibernate是因為在一些系統裡資料量大或是更新比較頻繁,而這些原因就會因為hibernate的快取機制導致系統記憶體消耗過大, 系統性能下降,還有一些保密性較高的如:財務資料,私人資訊等系統也不適合hibernate,不能使用sql的很多功能 儲存過程等。 jdbc與hibernate不能共存,因為會導致hibernate的快取失效。 21 用過hibernate註解嗎 說出幾個 答: @Entity:標記為持久類對映 @Table:指定表名 @Id @GeneratedValue @GenericGenerator:主鍵生成機制 @OneToMany @ManyToOne @JoinColumn:關聯欄位 其它註解: @Resource:標註在物件上,可以代替以前的set方法。 @Controller:表示action層。 @Service:表示service層。 @Repository:表示dao層。 22 hibernate為什麼能跨資料庫? 答:因為hibernate是ORM模式的框架,ORM就一項專門為了解決面向物件與關係資料庫不匹配而產生的一項技術, 因此在它的底層封裝了很多資料庫的方言,實現了跨資料庫的功能,根據配置的方言,產生不同的sql,使用URL通過元資料得到需要使用什麼資料庫。 使用hibernate碰到什麼問題? 1. 大資料量問題。 2. hibernate最好不要與其它系統共存,如:JDBC。 3. 使用一級快取的問題,當Session關閉后里面的資料就沒有了,因為不能控制,所以要注意大批量操作資料時可能造成記憶體溢位。 4. 使用二級快取的問題,要注意它的命中率,如果命中率太低對系統性能的消耗會很大。 5. 使用快取都會有存在無效資料的問題,使用快取應該注意查詢要大於修改,而且資料量不要過大。 23 效能優化 1.懶載入 2.List 和 iterator 3.批量處理 4.無狀態session 5.分頁