(1)、hibernate是封裝了jdbc的一個面向關係映射(ORM)的數據庫鏈接方式;而JDBC是一個關係型數據庫鏈接方式;java
(2)、JDBC與hibernate鏈接數據庫的方式大體相同,但hibernate將配置信息寫在XML中;spring
(3)、hibernate用HQL查詢,結果返回的是List<Object>,而JDBC用SQL查詢,結果返回的是ResultSet,要經過bean方式封裝到對象中;數據庫
(4)、hibernate的 HQL語句有專門的Dao層,而JDBC沒有,這樣當數據庫修改時,hibernate只須要修改Dao層便可,而JDBC修改的代碼量就多不少;apache
(5)、當處理一樣的SQL語句時,hibernate不會重複處理,而JDBC每一次都要進行處理,這樣hibernate的效率就遠遠高於JDBC;編程
(6)、JDBC在性能上,靈活性比hibernate要好,當對多表或者複雜的數據庫進行操做時,用JDBC好;緩存
(7)、「精心編寫」的JDBC必定是性能最好的。再級聯關係較多的時候,用hibernate應該比jdbc強,安全
(8)、用hibernate大大減小了代碼量的編寫;服務器
1.struts是控制頁面跳轉;struts是控制層和視圖層,負責JSP頁面的展現和交互。session
2.hibernate負責和數據庫的鏈接與操做;hibernate 是持久化層,負責數據的存儲和檢索。併發
3.Spring 減 少耦合,功能完成的層次分的很清楚;Spring是業務邏輯層,負責具體業務邏輯的實現,核心是IOC 和麪向AOP 編程,spring與struts和hibernate整合後,做爲一個IoC容器,所以能夠對struts和hibernate實施監控;能夠作安全, 日誌等一系列AOP的工做。
1 客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2 這 個請求通過一系列的過濾器(Filter),FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來 決定這個請是否須要調用某個Action,ActionServlet類是關鍵的控制器部件,全部的Action都繼承自 org.apache.struts.ation.Action類;
3 若是ActionMapper決定須要調用某個Action,FilterDispatcher把請求的處理交給Action執行,執行完畢, struts.xml中的配置找到對應的返回結果。
1) 在 Action實現類方面的對比:Struts 1要求Action類繼承一個抽象基類; Struts 2 Action類能夠實現一個Action接口,也能夠實現其餘接口,使可選和定製的服務成爲可能。Struts 2提供一個ActionSupport基類去實現經常使用的接口。即便Action接口不是必須實現的,只有一個包含execute方法的POJO類均可以用 做Struts 2的Action。
2) 線程模式方面的對比:Struts 1 Action是單例模式而且必須是線程安全的,由於僅有Action的一個實例來處理全部的請求。單例策略限制了Struts 1 Action能作的事,而且要在開發時特別當心。Action資源必須是線程安全的或同步的;Struts 2 Action對象爲每個請求產生一個實例,所以沒有線程安全問題。
3) Servlet依賴方面的對比:Struts 1 Action依賴於Servlet API,由於Struts 1 Action的execute方法中有HttpServletRequest和HttpServletResponse方法。Struts 2 Action再也不依賴於Servlet API,從而容許Action脫離Web容器運行,從而下降了測試Action的難度。 固然,若是Action須要直接訪問HttpServletRequest和HttpServletResponse參數,Struts 2 Action仍然能夠訪問它們。大部分時候Action都無需直接訪問HttpServetRequest和HttpServletResponse,從 而給開發者更多靈活的選擇。
4) 封裝請求參數的對比:Struts 1使用ActionForm對象封裝用戶的請求參數,全部的ActionForm必須繼承一個基類:ActionForm。普通的JavaBean不能用 做ActionForm,所以,開發者必須建立大量的ActionForm類封裝用戶請求參數。雖然Struts 1提供了動態ActionForm來簡化ActionForm的開發,但依然須要在配置文件中定義ActionForm;Struts 2直接使用Action屬性來封裝用戶請求屬性,避免了開發者須要大量開發ActionForm類的煩瑣, Struts 2提供了Model Driven模式,可讓開發者使用單獨的Model對象來封裝用戶請求參數,但該Model對象無需繼承任何Struts 2基類,是一個POJO,從而下降了代碼污染。
5) 表達式語言方面的對比:Struts 1整合了JSTL,所以可使用JSTL表達式語言。這種表達式語言有基本對象圖遍歷,但在對集合和索引屬性的支持上則功能不強;Struts 2可使用JSTL,但它整合了一種更強大和靈活的表達式語言:OGNL,所以Struts 2下的表達式語言功能更增強大。
6) 類型轉換的對比:Struts 1 ActionForm 屬性一般都是String類型。Struts 1使用Commons-Beanutils進行類型轉換,每一個類一個轉換器,轉換器是不可配置的;Struts 2使用OGNL進行類型轉換,支持基本數據類型和經常使用對象之間的轉換。
7) Action執行控制的對比:Struts 1支持每個模塊對應一個請求處理,可是模塊中的全部Action必須共享相同的生命週期。Struts 2支持經過攔截器堆棧(Interceptor Stacks)爲每個Action建立不一樣的生命週期。開發者能夠根據須要建立相應堆棧,從而和不一樣的Action一塊兒使用。
建立action對象資源浪費不是特別大,只要在設計的時候注意不要把一些比較重的資源放到全局變量和構造方法裏面就行了。另外容器裏有很好的垃圾回收機制,只要有一個action實例不用,就會立刻回收處理。因此服務器是徹底抗的住的。
由於二級緩存維護的問題,hibernate查詢數據後要進行持久化對象;好比查詢每一行都進行ORMapping,速度是會比較慢的;
加快方法:使用延遲加載:lazy=true;或者建立索引加快查詢速度;或者減小查詢字段;
解決方法:若是底層數據庫(如Oracle)支持存儲過程,也能夠經過存儲過程來執行批量更新。存儲過程直接在數據庫中運行,速度更加快。
hibernate.cfg.xml文件主要配置session-factory的數據源配置,而自增加配置在hbm.xml文件裏面的每一個表中id部分裏面的generate上;
工做原理
前提:在hibernate.cfg.xml文件中配置數據庫鏈接;其次寫domain.hbm.xml配置文件;
(1)、啓動服務器,讀取配置信息,建立sessionFactory;
(2)、Configuration conf = new Configuration().configure("hibernate.cfg.xml"); //實例化configuration對象;
(3)、SessionFactory sessionFactory = conf.buildSessionFactory(); //建立一個SessionFactory對象;
(4)、Session session = sessionFactory.openSession(); //建立session對象,打開一個Session;
(5)、Transaction tx = session.beginTransaction().begin(); //開啓事務;
(6)、添加要對數據庫進行操做信息;
(7)、session.save(user);//保存信息;
(8)、tx.commit();//提交;
爲何要用
1.對JDBC訪問數據庫的代碼作了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。
2.Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工做
3.hibernate使用Java反射機制,而不是字節碼加強程序來實現透明性。
4.hibernate的性能很是好,由於它是個輕量級框架。映射的靈活性很出色。它支持各類關係數據庫,從一對一到多對多的各類複雜關係。
當Hibernate在查詢數據的時候,數據並無存在與內存中,當程序真正對數據的操做時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提升了服務器的性能。
答:session/sessionFactory/configuration/transcation/query
HQL、SQL、Criteria;
第一種方式:Hibernate繼承關係樹的每一個具體類對應一個表:關係數據模型徹底不支持域模型中的繼承關係和多態。
第二種方式:Hibernate繼承關係樹的根類對應一個表:對關係數據模型進行很是規設計,在數據庫表中加入額外的區分子類型的字段。經過這種方式,可使關係數據模型支持繼承關係和多態。
第三種方式:Hibernate繼承關係樹的每一個類對應一個表:在關係數據模型中用外鍵參照關係來表示繼承關係。
答:主要解決數據持久化的問題
一級緩存:
Session 有一個內置的緩存,其中存放了被當前工做單元加載的對象。
每一個Session 都有本身獨立的緩存,且只能被當前工做單元訪問。
二級緩存:
SessionFactory的外置的可插拔的緩存插件。其中的數據可被多個Session共享訪問。
SessionFactory的內置緩存:存放了映射元數據,預約義的Sql語句。
(1).臨時狀態 (transient)又叫暫態:剛用new建立,沒被持久化,沒在session緩存中;
特徵:
1】不處於Session 緩存中
2】數據庫中沒有對象記錄
Java如何進入臨時狀態
1】經過new語句剛建立一個對象時
2】當調用Session 的delete()方法,持久化狀態à臨時
(2).持久化狀態(persisted):被持久化,加入到session緩存中;
特徵:
1】處於Session 緩存中
2】持久化對象數據庫中沒有對象記錄
3】Session 在特定時刻會保持兩者同步
Java如何進入持久化狀態
1】Session 的save() 臨時à持久化狀態
2】Session 的load(),get()方法返回的對象 臨時à持久化狀態
3】Session 的find()返回的list集合中存放的對象 臨時à持久化狀態
4】Session 的update(),saveOrUpdate() 遊離à持久化
(3).遊離狀態(detached):被持久化,沒在session緩存中;
特徵:
1】再也不位於Session 緩存中
2】遊離對象由持久化狀態轉變而來,數據庫中可能還有對應記錄。
Java如何進入 持久化狀態à遊離狀態
1】Session 的close()方法
2】Session 的evict()方法,從緩存中刪除一個對象。提升性能。少用。
一對多關係分爲單向一對多關係和雙向一對多關係。
單向一對多關係只能經過主控方對被動方進行級聯更新。
雙向一對多關係其實是「一對多」與「多對一」關聯的組合,也就是說咱們必須在主控方配置單向一對多關係的基礎上,在被控方配置與其對應的多對一關係。
雙向一對多的關係除了避免約束違例和提升性能的好處以外,還帶來另一個優勢,因爲創建了雙向關聯,咱們能夠在關聯雙方中任意一方,訪問關聯的另外一方。
答:ORM是面向對象關係映射的意思;
應用:主要是開發人員就能夠把對數據庫的操做轉化爲對這些對象的操做;
(1)、悲觀鎖:在整個數據處理過程當中,數據處於鎖定狀態,外界沒法修改;
實現:query.setLockMode( " user " ,LockMode.UPGRADE); // 加鎖
(2)、樂觀鎖:更改數據庫表後,將爲數據表增長一個版本標識;大大提升併發效率;
實現:爲TUser的class描述符添加optimistic-lock屬性:
< hibernate - mapping >
< class
name = " org.hibernate.sample.TUser "
table = " t_user "
dynamic - update = " true "
dynamic - insert = " true "
optimistic - lock = " version "
>
……
</ class >
</ hibernate - mapping >
答:lazy,就是延時加載。
以最簡單的parent和child爲例子:一個parent能夠有多個child,一個child只有一個parent。
當parent類的child屬性的lazy爲true,那麼當select parent的時候,他的child不會立刻被select,一直延遲到他的child須要被讀寫的時候再去select。
當parent類的child屬性的lazy爲false,那麼select parent的時候,他的child會立刻被select。
inverse,用於外鍵維護的控制。
當inverse爲false,則在插入表數據以後,會再插入外鍵維護的記錄。
當inverse爲true,則在插入表數據的同時,插入外鍵維護的記錄。
在非多對多的表關係中:
仍是以parent和child爲例子。假設1個parent有3個child,那麼:
當inverse爲false,則先insert 1 條 parent,再insert 3 條 child,再insert 3 個child的parent ID,一共7次insert。
當inverse爲true,則先insert 1 條 parent,再insert 3 條 child,固然這3次insert是同時完成插入parent ID的,因此一共4次insert。
總結:在非多對多的表關係中,inverse永遠爲ture。
在多對多的表關係中:
中間表的外鍵維護一般由一方進行維護。
因此2個多方,1個inverse爲ture,1個inverse爲false。中間表會由inverse爲false的一方維護。
總結:選擇數據比較多的一方維護中間表的效率會比較高。
cascade,表的級聯。
若是你熟悉數據庫,表級聯能夠設置在數據庫上。
若是你選擇設置在配置文件中,則相應的你的系統會更方便的在各個數據庫之間進行移植。
級聯具體狀況就看業務需求了。關於級聯,不明白的可查閱數據庫基礎理論。沒什麼好多說的。
fetch,就是加載子表信息所採用的方式,select或者join
如下是我我的對這個屬性的理解:
xml配置文件中能夠不配置,採用默認的。而他真正的做用在於:
1). 一般狀況爲了保證效率,lazy的配置都是true的。好比有個頁面須要顯示parent列表,只須要parent的name屬性和create time屬性,由於不涉及子表信息,lazy爲false的配置將大大影響效率。這樣,咱們就擁有了hibernate的高性能。
2). 特殊狀況下,咱們又但願lazy爲false,即當編輯某一個parent的時候,馬上得到parent的子表,乃至子表的信息(例如當咱們採用分層結構 時,當信息到視圖層時,hibernate的session已經斷開了,因此要在邏輯層完成全部信息的載入)。咱們就能夠在HQL中寫 left/right outer/inner join fetch實現此功能。這樣,咱們又得到了臨時的靈活性。
(1).減小訪問數據庫的頻率。
(2).保證緩存中的對象與數據庫中的相關記錄保持同步。
(3).保證不出現訪問對象圖的死循環,以及由死循環引發的JVM堆棧溢出異常。清理緩存時,會順序執行一些SQL語句。
攔截器與過濾器的區別:
攔截器是基於java的反射機制的,而過濾器是基於函數回調。
攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
攔截器只能對action請求起做用,而過濾器則能夠對幾乎全部的請求起做用。
攔截器能夠訪問action上下文、值棧裏的對象,而過濾器不能訪問。
在action的生命週期中,攔截器能夠屢次被調用,而過濾器只能在容器初始化時被調用一次
執行順序:過濾前 - 攔截前 - Action處理 - 攔截後 - 過濾後。我的認爲過濾是一個橫向的過程,首先把客戶端提交的內容進行過濾(例如未登陸用戶不能訪問內部頁面的處理);過濾經過後,攔截器將檢查用戶提交數據的驗證,作一些前期的數據處理,接着把處理後的數據發給對應的Action;