<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    zx_bing

    人生路漫漫,多學(xué)些知識總是有益處的
    隨筆 - 32, 文章 - 0, 評論 - 0, 引用 - 0
    數(shù)據(jù)加載中……

    外鍵查詢 遇到錯誤:could not initialize proxy - the owning Session was close

    關(guān)于lazy機(jī)制:

    延遲初始化錯誤是運(yùn)用Hibernate開發(fā)項(xiàng)目時最常見的錯誤。如果對一個類或者集合配置了延遲檢索策略,那么必須當(dāng)代理類實(shí)例或代理集合處于持久化狀態(tài)(即處于Session范圍內(nèi))時,才能初始化它。如果在游離狀態(tài)時才初始化它,就會產(chǎn)生延遲初始化錯誤。

    下面把Customer.hbm.xml文件的<class>元素的lazy屬性設(shè)為true,表示使用延遲檢索策略:

    <class name="mypack.Customer" table="CUSTOMERS" lazy="true">

    當(dāng)執(zhí)行Session的load()方法時,Hibernate不會立即執(zhí)行查詢CUSTOMERS表的select語句,僅僅返回Customer類的代理類的實(shí)例,這個代理類具由以下特征:

    (1) 由Hibernate在運(yùn)行時動態(tài)生成,它擴(kuò)展了Customer類,因此它繼承了Customer類的所有屬性和方法,但它的實(shí)現(xiàn)對于應(yīng)用程序是透明的。
    (2) 當(dāng)Hibernate創(chuàng)建Customer代理類實(shí)例時,僅僅初始化了它的OID屬性,其他屬性都為null,因此這個代理類實(shí)例占用的內(nèi)存很少。
    (3)當(dāng)應(yīng)用程序第一次訪問Customer代理類實(shí)例時(例如調(diào)用customer.getXXX()或customer.setXXX()方法), Hibernate會初始化代理類實(shí)例,在初始化過程中執(zhí)行select語句,真正從數(shù)據(jù)庫中加載Customer對象的所有數(shù)據(jù)。但有個例外,那就是當(dāng)應(yīng)用程序訪問Customer代理類實(shí)例的getId()方法時,Hibernate不會初始化代理類實(shí)例,因?yàn)樵趧?chuàng)建代理類實(shí)例時OID就存在了,不必到數(shù)據(jù)庫中去查詢。

    提示:Hibernate采用CGLIB工具來生成持久化類的代理類。CGLIB是一個功能強(qiáng)大的Java字節(jié)碼生成工具,它能夠在程序運(yùn)行時動態(tài)生成擴(kuò)展 Java類或者實(shí)現(xiàn)Java接口的代理類。關(guān)于CGLIB的更多知識,請參考:http://cglib.sourceforge.net/。

    以下代碼先通過Session的load()方法加載Customer對象,然后訪問它的name屬性:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    customer.getName();
    tx.commit();

    在運(yùn)行session.load()方法時Hibernate不執(zhí)行任何select語句,僅僅返回Customer類的代理類的實(shí)例,它的OID為1,這是由load()方法的第二個參數(shù)指定的。當(dāng)應(yīng)用程序調(diào)用customer.getName()方法時,Hibernate會初始化Customer代理類實(shí)例,從數(shù)據(jù)庫中加載Customer對象的數(shù)據(jù),執(zhí)行以下select語句:

    select * from CUSTOMERS where ID=1;
    select * from ORDERS where CUSTOMER_ID=1;

    當(dāng)<class>元素的lazy屬性為true,會影響Session的load()方法的各種運(yùn)行時行為,下面舉例說明。

    1.如果加載的Customer對象在數(shù)據(jù)庫中不存在,Session的load()方法不會拋出異常,只有當(dāng)運(yùn)行customer.getName()方法時才會拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
    mypack.Customer

    2.如果在整個Session范圍內(nèi),應(yīng)用程序沒有訪問過Customer對象,那么Customer代理類的實(shí)例一直不會被初始化,Hibernate不會執(zhí)行任何select語句。以下代碼試圖在關(guān)閉Session后訪問Customer游離對象:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    tx.commit();
    session.close();
    customer.getName();

    由于引用變量customer引用的Customer代理類的實(shí)例在Session范圍內(nèi)始終沒有被初始化,因此在執(zhí)行customer.getName()方法時,Hibernate會拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

    由此可見,Customer代理類的實(shí)例只有在當(dāng)前Session范圍內(nèi)才能被初始化。

    3.net.sf.hibernate.Hibernate類的initialize()靜態(tài)方法用于在Session范圍內(nèi)顯式初始化代理類實(shí)例,isInitialized()方法用于判斷代理類實(shí)例是否已經(jīng)被初始化。例如:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    if(!Hibernate.isInitialized(customer))
    Hibernate.initialize(customer);
    tx.commit();
    session.close();
    customer.getName();

    以上代碼在Session范圍內(nèi)通過Hibernate類的initialize()方法顯式初始化了Customer代理類實(shí)例,因此當(dāng)Session關(guān)閉后,可以正常訪問Customer游離對象。

    4.當(dāng)應(yīng)用程序訪問代理類實(shí)例的getId()方法時,不會觸發(fā)Hibernate初始化代理類實(shí)例的行為,例如:

    tx = session.beginTransaction();
    Customer customer=(Customer)session.load(Customer.class,new Long(1));
    customer.getId();
    tx.commit();
    session.close();
    customer.getName();

    當(dāng)應(yīng)用程序訪問customer.getId()方法時,該方法直接返回Customer代理類實(shí)例的OID值,無需查詢數(shù)據(jù)庫。由于引用變量 customer始終引用的是沒有被初始化的Customer代理類實(shí)例,因此當(dāng)Session關(guān)閉后再執(zhí)行customer.getName()方法, Hibernate會拋出以下異常:

    ERROR LazyInitializer:63 - Exception initializing proxy
    net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed


    解決方法:

    由于hibernate采用了lazy=true,這樣當(dāng)你用hibernate查詢時,返回實(shí)際為利用cglib增強(qiáng)的代理類,但其并沒有實(shí)際填充;當(dāng)你在前端,利用它來取值(getXXX)時,這時Hibernate才會到數(shù)據(jù)庫執(zhí)行查詢,并填充對象,但此時如果和這個代理類相關(guān)的session已關(guān)閉掉,就會產(chǎn)生種錯誤.
    在做一對多時,有時會出現(xiàn)"could not initialize proxy - clothe owning Session was sed,這個好像是hibernate的緩存問題.問題解決:需要在<many-to-one>里設(shè)置lazy="false". 但有可能會引發(fā)另一個異常叫

    failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

    此異常解決方案請察看本人博客(http://hi.baidu.com/kekemao1)的Hibernate異常中的《failed to lazily initialize a collection of role異常》

    ?
    解決方法:在web.xml中加入
    <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class>
         org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
    就可以了;

    參考了:
    Hibernate與延遲加載:

    Hibernate對象關(guān)系映射提供延遲的與非延遲的對象初始化。非延遲加載在讀取一個對象的時候會將與這個對象所有相關(guān)的其他對象一起讀取出來。這有時會導(dǎo)致成百的(如果不是成千的話)select語句在讀取對象的時候執(zhí)行。這個問題有時出現(xiàn)在使用雙向關(guān)系的時候,經(jīng)常會導(dǎo)致整個數(shù)據(jù)庫都在初始化的階段被讀出來了。當(dāng)然,你可以不厭其煩地檢查每一個對象與其他對象的關(guān)系,并把那些最昂貴的刪除,但是到最后,我們可能會因此失去了本想在ORM工具中獲得的便利。


    一個明顯的解決方法是使用Hibernate提供的延遲加載機(jī)制。這種初始化策略只在一個對象調(diào)用它的一對多或多對多關(guān)系時才將關(guān)系對象讀取出來。這個過程對開發(fā)者來說是透明的,而且只進(jìn)行了很少的數(shù)據(jù)庫操作請求,因此會得到比較明顯的性能提升。這項(xiàng)技術(shù)的一個缺陷是延遲加載技術(shù)要求一個Hibernate會話要在對象使用的時候一直開著。這會成為通過使用DAO模式將持久層抽象出來時的一個主要問題。為了將持久化機(jī)制完全地抽象出來,所有的數(shù)據(jù)庫邏輯,包括打開或關(guān)閉會話,都不能在應(yīng)用層出現(xiàn)。最常見的是,一些實(shí)現(xiàn)了簡單接口的DAO實(shí)現(xiàn)類將數(shù)據(jù)庫邏輯完全封裝起來了。一種快速但是笨拙的解決方法是放棄DAO模式,將數(shù)據(jù)庫連接邏輯加到應(yīng)用層中來。這可能對一些小的應(yīng)用程序有效,但是在大的系統(tǒng)中,這是一個嚴(yán)重的設(shè)計缺陷,妨礙了系統(tǒng)的可擴(kuò)展性。

    在Web層進(jìn)行延遲加載

    幸運(yùn)的是,Spring框架為Hibernate延遲加載與DAO模式的整合提供了一種方便的解決方法。對那些不熟悉Spring與Hibernate集成使用的人,我不會在這里討論過多的細(xì)節(jié),但是我建議你去了解Hibernate與Spring集成的數(shù)據(jù)訪問。以一個Web應(yīng)用為例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我們可以隨意選擇一個類來實(shí)現(xiàn)相同的功能。兩種方法唯一的不同就在于interceptor在Spring容器中運(yùn)行并被配置在web應(yīng)用的上下文中,而Filter在Spring之前運(yùn)行并被配置在web.xml中。不管用哪個,他們都在請求將當(dāng)前會話與當(dāng)前(數(shù)據(jù)庫)線程綁定時打開Hibernate會話。一旦已綁定到線程,這個打開了的Hibernate會話可以在DAO實(shí)現(xiàn)類中透明地使用。這個會話會為延遲加載數(shù)據(jù)庫中值對象的視圖保持打開狀態(tài)。一旦這個邏輯視圖完成了,Hibernate會話會在Filter的doFilter方法或者Interceptor的postHandle方法中被關(guān)閉。下面是每個組件的配置示例:



    Interceptor的配置:


    <beans>
    <bean id="urlMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="interceptors">
    <list>
    <ref bean="openSessionInViewInterceptor"/>
    </list>
    </property>
    <property name="mappings">

    </bean>

    <bean name="openSessionInViewInterceptor"
    class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
    <property name="sessionFactory"><ref bean="sessionFactory"/></property>
    </bean>
    </beans>

    Filter的配置


    <web-app>

    <filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
    org.springframework.orm.hibernate.support.OpenSessionInViewFilter
    </filter-class>
    </filter>

    <filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*. spring </url-pattern>
    </filter-mapping>

    </web-app>


    實(shí)現(xiàn)Hibernate的Dao接口來使用打開的會話是很容易的。事實(shí)上,如果你已經(jīng)使用了Spring框架來實(shí)現(xiàn)你的Hibernate Dao,很可能你不需要改變?nèi)魏螙|西。方便的HibernateTemplate公用組件使訪問數(shù)據(jù)庫變成小菜一碟,而DAO接口只有通過這個組件才可以訪問到數(shù)據(jù)庫。下面是一個示例的DAO:


    public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {

    public Product getProduct(Integer productId) {
    return (Product)getHibernateTemplate().load(Product.class, productId);
    }

    public Integer saveProduct(Product product) {
    return (Integer) getHibernateTemplate().save(product);
    }

    public void updateProduct(Product product) {
    getHibernateTemplate().update(product);
    }
    }


    在業(yè)務(wù)邏輯層中使用延遲加載

    即使在視圖外面,Spring框架也通過使用AOP 攔截器 HibernateInterceptor來使得延遲加載變得很容易實(shí)現(xiàn)。這個Hibernate 攔截器透明地將調(diào)用配置在Spring應(yīng)用程序上下文中的業(yè)務(wù)對象中方法的請求攔截下來,在調(diào)用方法之前打開一個Hibernate會話,然后在方法執(zhí)行完之后將會話關(guān)閉。讓我們來看一個簡單的例子,假設(shè)我們有一個接口BussinessObject:


    public     interface    BusinessObject     {
    public     void    doSomethingThatInvolvesDaos();
    }
    類BusinessObjectImpl實(shí)現(xiàn)了BusinessObject接口:

    public     class    BusinessObjectImpl    implements    BusinessObject     {
    public     void    doSomethingThatInvolvesDaos()     {
    //    lots of logic that calls
    //    DAO classes Which access
    //    data objects lazily 





    通過在Spring應(yīng)用程序上下文中的一些配置,我們可以讓將調(diào)用BusinessObject的方法攔截下來,再令它的方法支持延遲加載。看看下面的一個程序片段:



    <beans>
    <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
    <property name="sessionFactory">
    <ref bean="sessionFactory"/>
    </property>
    </bean>
    <bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl">
    <property name="someDAO"><ref bean="someDAO"/></property>
    </bean>
    <bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target"><ref bean="businessObjectTarget"/></property>
    <property name="proxyInterfaces">
    <value>com.acompany.BusinessObject</value>
    </property>
    <property name="interceptorNames">
    <list>
    <value>hibernateInterceptor</value>
    </list>
    </property>
    </bean>
    </beans>

    當(dāng)businessObject被調(diào)用的時候,HibernateInterceptor打開一個Hibernate會話,并將調(diào)用請求傳遞給BusinessObjectImpl對象。當(dāng)BusinessObjectImpl執(zhí)行完成后,HibernateInterceptor透明地關(guān)閉了會話。應(yīng)用層的代碼不用了解任何持久層邏輯,還是實(shí)現(xiàn)了延遲加載。


    在單元測試中測試延遲加載

    最后,我們需要用J-Unit來測試我們的延遲加載程序。我們可以輕易地通過重寫TestCase類中的setUp和tearDown方法來實(shí)現(xiàn)這個要求。我比較喜歡用這個方便的抽象類作為我所有測試類的基類。


    public abstract class MyLazyTestCase extends TestCase {

    private SessionFactory sessionFactory;
    private Session session;

    public void setUp() throws Exception {
    super.setUp();
    SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
    session = SessionFactoryUtils.getSession(sessionFactory, true);
    Session s = sessionFactory.openSession();
    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

    }

    protected Object getBean(String beanName) {
    //Code to get objects from Spring application context
    }

    public void tearDown() throws Exception {
    super.tearDown();
    SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    Session s = holder.getSession();
    s.flush();
    TransactionSynchronizationManager.unbindResource(sessionFactory);
    SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
    }

    --------------------------------------------------------------
    --------------------------------------------------------------

    Java代碼 復(fù)制代碼 收藏代碼
    1. <?xml version="1.0"?> 
    2. <!DOCTYPE hibernate-mapping PUBLIC 
    3.     "-//Hibernate/Hibernate Mapping DTD//EN" 
    4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
    5. <hibernate-mapping package="com.isoftstone.lms.model"
    6.     <class name="Order" table="sv_order"
    7.         <id name="orderId" column="sv_order_id" type="string"
    8.             <generator class="sequence"
    9.                 <param name="sequence">SEQ_ORDERID</param> 
    10.             </generator> 
    11.         </id> 
    12.          
    13.         many-to-one name="style" column="sv_style_id" lazy="false" /> 
    14.         <many-to-one name="state" column="sv_state_id"  lazy="false"/> 
    15.         <many-to-one name="client" column="sv_client_id" lazy="false" /> 
    16.         <many-to-one name="baseOrder" column="sv_order_baseid"  lazy="false"/> 
    17.         <property name="orderNo" column="sv_order_orderno" type="long" /> 
    18.         <property name="createDate" column="sv_order_createdate" type="date" /> 
    19.         <property name="sendDate" column="sv_order_senddate" type="string" /> 
    20.         <property name="sendAddress" column="sv_order_sendAddress" type="string" /> 
    21.         <property name="accepter" column="sv_order_accepter" type="string" /> 
    22.         <property name="postNo" column="sv_order_postNo" type="string" /> 
    23.         <property name="phone" column="sv_order_phone" type="string" /> 
    24.         <property name="totalMoney" column="sv_order_totalmoney" type="double" /> 
    25.         <property name="isinvoice" column="sv_order_isinvoice" type="int" /> 
    26.         <property name="remark" column="sv_order_remark" type="string" /> 
    27.          
    28.         <set name="orderGoodss" inverse="true" lazy="extra" cascade="all"
    29.             <key column="sv_order_id"/> 
    30.             <one-to-many class="OrderGoods"/> 
    31.         </set> 
    32.     </class
    33. </hibernate-mapping> 

    [color=red]
    Java代碼 復(fù)制代碼 收藏代碼
    1. <many-to-one name="style" column="sv_style_id" lazy="false" /> 
    2. <many-to-one name="state" column="sv_state_id"  lazy="false"/> 
    3. <many-to-one name="client" column="sv_client_id" lazy="false" /> 
    4. <many-to-one name="baseOrder" column="sv_order_baseid"  lazy="false"/> 
    [/color]

    posted on 2012-07-27 14:13 zx_bing 閱讀(170) 評論(0)  編輯  收藏 所屬分類: Hibernate

    主站蜘蛛池模板: 男人免费视频一区二区在线观看| 日本在线免费观看| 亚洲日韩中文无码久久| 最近2022中文字幕免费视频| 欧洲亚洲国产精华液| 国产亚洲真人做受在线观看| 国产在线国偷精品产拍免费| 一区二区在线免费视频| 99亚洲精品高清一二区| 免费国产怡红院在线观看| 久久这里只精品99re免费| 日韩欧美亚洲中文乱码| 亚洲av无码乱码国产精品fc2| 最近高清国语中文在线观看免费| 羞羞视频免费网站在线看| 亚洲熟妇丰满xxxxx| 亚洲成av人片在线观看无码不卡| 最近中文字幕无吗高清免费视频| 中文字幕成人免费高清在线视频| 国产成人精品日本亚洲11| 亚洲伊人久久大香线蕉综合图片| 成人免费a级毛片| 嫩草成人永久免费观看| 黄页网站在线视频免费| 亚洲日韩中文字幕| 亚洲午夜国产精品无码老牛影视| 国外成人免费高清激情视频| 一级毛片成人免费看免费不卡| 牛牛在线精品观看免费正| 亚洲人成自拍网站在线观看| 亚洲视频在线免费观看| 中文字幕精品亚洲无线码一区应用| 国产成人午夜精品免费视频| 亚洲一区免费观看| 国产成人AV免费观看| 免费人成动漫在线播放r18| 亚洲熟妇AV乱码在线观看| 久久亚洲sm情趣捆绑调教| 亚洲va无码手机在线电影| 亚洲五月午夜免费在线视频| 国产精品久免费的黄网站|