<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # Hibernate優化方案 ## HQL優化 1. 使用參數綁定 使用綁定參數的原因是讓數據庫一次解析SQL,對后續的重復請求可以使用用生成好的執行計劃,這樣做節省CPU時間和內存 2. 避免SQL注入 盡量少使用NOT 如果where子句中包含not關鍵字,那么執行時該字段的索引失效。 3. 盡量使用where來替換having Having在檢索出所有記錄后才對結果集進行過濾,這個處理需要一定的開銷,而where子句限制記錄的數目,能減少這方面的開銷 4. 減少對表的查詢 在含有子查詢的HQL中,盡量減少對表的查詢,降低開銷 5. 使用表的別名 當在HQL語句中連接多個表時,使用別名,提高程序閱讀性,并把別名前綴與每個列上,這樣一來,可以減少解析時間并減少列歧義引起的語法錯誤。 6. 實體的更新與刪除 在hibernate3以后支持hql的update與delete操作 ~~~ String hql = "update User user set user age = 20 where user age = 18"; Query queryupdate = session.createQuery(hql); int ret = queryupdate.executeUpdate(); ~~~ ### 一級緩存優化 一級緩存也叫做session緩存,在一個hibernate session有效,這級緩存的可干預性不強,大多于hibernate自動管理,但它提供清除緩存的方法,這在大批量增加(更新)操作是有效果的,例如,同時增加十萬條記錄,按常規進行,很可能會出現異常,這時可能需要手動清除一級緩存,session.evict以及session.clear. ## 檢索策略(抓取策略) ### 延遲加載 延遲加載 是hibernate為提高程序執行的效率而提供的一種機制,即只有真正使用該對象的數據時才會創建。 load方法采用的策略延遲加載. get方法采用的策略立即加載。 檢索策略分為兩種: 1. 類級別檢索 2. 關聯級別檢索 ### 類級別檢索 類級別檢索是通過session直接檢索某一類對應的數據,例如 ~~~ Customer c=session.load(Customer.class, 1); Session.createQuery("from Order"); ~~~ 類級別檢索策略分為立即檢索與延遲檢索,默認是延遲檢索,類級別的檢索策略可以通過元素的lazy屬性來設置 ,默認值是true 在hbm配置文件中設置 ~~~ <class name="Customer" table="t_customer" catelog="hibernateTest" lazy="true"> ~~~ 在類中使用注解 ~~~ @Proxy(lazy=true) public class Customer { ~~~ 如果將lazy設置為false,代表類級別檢索也使用立即檢索. 這時候load與get就一樣,都是立即檢索 如果對一個延遲代理對象進行初始化? ~~~ Customer c1 = session.load(Customer.class, 1); Hibernate.inintialize(c1); ~~~ ### 關聯級別檢索 查詢到某個對象,獲得其關聯的對象或屬性,這種稱為關聯級別檢索,例如 ~~~ c.getOrders().size(); c.getName(); ~~~ 對于關聯級別檢索我們就要研究其檢索策略(抓取策略) ### 抓取策略介紹 指的是查找到某個對象后,通過這個對象去查詢關聯對象的信息時的一種策略。 一對一`<one-to-one>` 一對多(多對一)`<set>`下有`<one-to-many> <many-to-one>` 多對多`<set>`下有`<many-to- many>` 我們主要是在`<set>`與`<many-to-one>`或`<one-to-one>`上設置fetch lazy 例如:查詢一個客戶,要關聯查詢它的訂單 客戶是一的一方,在客戶中有set集合來描述其訂單,在配置中我們是使用 ~~~ <set> <one-to-many> </set>.. ~~~ 可以在set標簽上設置兩個屬性 fetch lazy Fetch主要描述的是SQL語句的格式(例如是多條,子查詢,多表聯查 Lazy 控制SQL語句何時發送 例如:在查詢一個訂單時,要查詢客戶信息 `<many-to-one> 或<one-to-one>` 也可以設置fetch lazy Fetch主要描述的是SQL語句的格式(例如是多條,子查詢,多表聯查 Lazy 控制SQL語句何時發送 總結: 講解抓取策略 在兩方面設置 ~~~ <set fetch="" lazy=""> <many-to-one fetch="" lazy=""> <one-to-one> ~~~ ### 注解配置抓取策略 問題:如何使用注解來設置 在`<setse>`設置的fetch與lazy可以使用下面注解來描述 ~~~ @Fetch(FetchMode.SUBSELECT) @LazyCollection(LazyCollectionOption.EXTRA) private Set<Order> orders = new HashSet<Order>(); ~~~ ~~~ <set name="orders" inverse="true" cascade="save-update" lazy="true" fetch="join"> ~~~ 在`<many-to-one>`或`<one-to-one>`上設置fetch與lazy ~~~ @Fetch(FetchMode.SELECT) @LazyToOne(LazyToOneOption.FALSE) private Customer c; ~~~ ~~~ <!-- 多對多 --> <many-to-one fetch="join" lazy="false"></many-to-one> ~~~ ## set上的fetch與lazy set上的fetch與lazy它主要是用于設置關聯的集合信息的抓取策略。 Fetch可取值有: 1. SELECT 多條簡單的sql (默認值) 2. JOIN 采用迫切左外連接 3. SUBSELECT 將生成子查詢的SQL lazy可取值有: 4. TURE 延遲檢索 (默認值) 5. FALSE 立即檢索 6. EXTRA 加強延遲檢索(及其懶惰) ~~~ //得到id=1的Customer Customer c = session.get(Customer.class ,1); //得到Customer關聯的order信息 int size = c.getOrders().size(); System.out.println(size); ~~~ ### 第一種組合 會首先查詢客戶信息,當需要訂單信息時,才會關聯查詢訂單信息 ~~~ @Fetch(FetchMode.SELECT) @LazyCollection(LazyCollectionOption.TRUE) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第二種組合 當查詢客戶信息時,就會將訂單信息也查詢,也就是說訂單信息沒有進行延遲 ~~~ @Fetch(FetchMode.SELECT) @LazyCollection(LazyCollectionOption.FALSE) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第三種組合 當查詢客戶信息時,不會查詢訂單信息,當需要訂單的個數時,也不會查詢訂單信息, 只會通過count來統計訂單個數。 當我們使用size(),contains()或isEmpty()方法時不會查詢訂單信息。 ~~~ @Fetch(FetchMode.SELECT) @LazyCollection(LazyCollectionOption.EXTRA) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第四種組合 如果fetch選擇的是join方案,那么lazy它會失效。 生成SQL將采用的是迫切左外連接(left outer join fetch) 會立即查詢。 ~~~ @Fetch(FetchMode.JOIN) @LazyCollection(LazyCollectionOption.FALSE) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第五種組合 會生成子查詢,但是我們在查詢訂單時采用的是延遲加載。 ~~~ @Fetch(FetchMode.SUBSELECT) @LazyCollection(LazyCollectionOption.TRUE) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第六種組合 會生成子查詢,在查詢客戶信息時,就會將訂單信息也查詢出來 ~~~ @Fetch(FetchMode.SUBSELECT) @LazyCollection(LazyCollectionOption.FALSE) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 第七種組合 在查詢訂單時,只會根據情況來確定是否要訂單信息,如果不需要,例如我們 程序中size操作,那么就會發出`select count(*) from Order where c_customer_id=?` ~~~ @Fetch(FetchMode.SUBSELECT) @LazyCollection(LazyCollectionOption.EXTRA) private Set<Order> orders = new HashSet<Order>(); ~~~ ### 結論 ~~~ <!-- lazy屬性:決定是否延遲加載 true(默認值):延遲加載,懶加載 false:立即加載 extra:極其懶惰 fetch屬性:決定加載策略,使用什么類型的sql語句加載集合數據 select(默認值):單表查詢加載 join:使用多表查詢加載集合 subselect:使用子查詢加載集合 --> ~~~ 結論為了提高效率 fetch的選擇上應選擇 select.lazy的取值應選擇true.全部使用默認值 no-session問題解決? 擴大session作用范圍 ~~~ Filter //前處理,打開session事務 chain.doFilter(request, response); //放行 //后處理,關閉session,事務 ~~~ ## One的一言fetch與lazy `<set fetch lazy>`它主要是設置在獲取到一的一方時,如果去查詢多的一方。 在`<many-to-one>或<one-to-one>`如果去查詢對方。 對于程序 就是在多的一方如何查詢一的主方信息 例如:獲取到一個訂單對象,要查詢客戶信息。 Fetch可取值: select 默認值,代表發送一條或多條簡單的select語句 join 發送一條迫切左外連接 lazy可取值 false 不采用延遲加載 proxy 默認值 是否采用延遲,需要另一方的類級別延遲策略來決定 no-proxy 不用研究 ~~~ //得到訂單 Order order = session.get(Order.class, 1); //得到訂單對應的客戶 Customer c = order.getC(); System.out.println(c.getName()); ~~~ ### 第一種組合 ~~~ @Fetch(FetchMode.SELECT) @LazyToOne(LazyToOneOption.PROXY) private Customer c; ~~~ 注意: Customer的類級別延遲策略 ~~~ @Proxy(lazy=true) public class Customer { ~~~ 當我們執行時,會首先發送一條sql只查詢訂單信息,客戶信息會延遲,只有真正需要客戶信息時,才會發送sql來查詢客戶信息. ### 第二種組合 ~~~ @Fetch(FetchMode.SELECT) @LazyToOne(LazyToOneOption.PROXY) private Customer c; ~~~ 注意: Customer的類級別延遲策略 ~~~ @Proxy(lazy=false) public class Customer { ~~~ 當查詢訂單時,不會對客戶信息進行延遲,立即查詢客戶信息 ### 第四種組合 ~~~ @Fetch(FetchMode.JOIN) @LazyToOne(LazyToOneOption.FALSE) private Customer c; ~~~ 如果fetch值為join,那么lazy失效 會發送一條迫切左外連接來查詢,也就是立即查詢 ## 批量抓取 我們在查詢多個對象的關聯對象時,可以采用批量抓取方式來對程序進行優化. 要想實現批量抓取: 可以在配置文件中 `batch-size`屬性來設置 可以使用注解 `@BatchSize(size=4)` 可以采用批量抓取來解決N+1問題. 抓取客戶的時候一次抓取幾個聯系人 查詢客戶,查詢訂單 ~~~ //得到所有客戶 List<Customer> list = session.createQuery("from Customer").list(); //得到客戶的訂單信息 for (Customer c : list) { System.out.println(c.getOrders().size()); } ~~~ 可以在客戶配置文件中配置`batch-size`,是在`<set>`標簽上 ~~~ @BatchSize(size=3) private Set<Order> orders = new HashSet<Order>(); ~~~ 查詢訂單,查詢客戶 ~~~ //得到所有訂單 List<Order> list = session.createQuery("from Order").list(); //得到客戶的信息 for (Order order : list) { System.out.println(order.getC().getName()); } //訂單一共有兩種,在查詢時會首先發送一條sql查詢出所有訂單,在根據訂單查詢客戶一共3條語句完成 ~~~ 訂單與客戶,客戶他是一個主表,訂單是一個從表 在設置批量抓取時都是在主表中設置 在配置文件中在主表的`<calss>`標簽上設置`batch-size` 在注解使用中 ~~~ @BatchSize(size=10) public class Customer { ~~~ 注意:無論是根據哪一方來查詢別一方,在進行批量抓取時,都是在父方來設置 如果是要查詢子信息,那么我們是在`<set>`上來設置 `batch-size`如果是從子方來查詢父方, 也是在父方設置在`<class>`設置`batch-size` **父與子區分** 有外鍵的表是子,從關聯方就是父(主)表
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看