Vysvetleni je strasne jednoduche. Pokud maji byt objekty nacitany pomoci
lazy, musi mit odkaz na otevreny session. To znamena, ze po celou dobu
zivota rodicovskeho objektu, musi byt session otevrena, co kdyby se
nejaky lazy parametr mel zrovna nacist.
To je znacne nehospodarne ne? Takze spring automaticky po ukonceni behu
vlakna session uzavre. No ale pak zjevne nemuze fungovat lazy. Jak z toho?
Prvni moznost je session zachytit a neumoznit jeji uvoneni. To znamena
ze nechate vlakno ktere vlastni session zit. Brzi se ale dostanete do
problemu.
Takze druha moznost je vyuzit vlastni metodiku lazy nacitani. Logicky by
se do kazde metody ktera vrati line nacitane objekty dalo pridat nacteni
z nejakeho dao readeru, jenze pak je tu potrebne odchytit ukladani
objektu rodicovskeho, aby se i lazy drzene objekty ukladali taky. Ale v
male aplikaci je to suverejne nejlepsi reseni. V podstate se tak
oprostite i od hibernate, vyhnete se spouste problemu a celou ORM si
udelate sam na miru. Cas ktery spotrebujete na vytvareni takovehoto ORM
modelu, je pri malych aplikacich (s malym mnozstvim tabulek) vyrazne
nizsi nez kolik poterbujete na zkroceni hibernate.
No ale ve vetsim projektu, se hibernate uz vyplati. Takze pak se logicky
nabizi moznost AOP. Spring ma specialni AOP object pro komunikaci s
hibernate. V definici pak vubec lazy nepouzivate a nacitani nechavate na
springu, ktery vse zaridi pres AOP:
<bean id="jHasEvidHibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="jHasEvidSessionFactory"/>
</property>
</bean>
<bean id="krajTarget" class="cz.apnetis.jhasevid.db.KrajClass">
<property name="association"><ref bean="association"/></property>
</bean>
<bean id="kraj"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="krajTarget"/></property>
<property name="proxyInterfaces">
<value>cz.apnetis.jhasevid.db.KrajInterface</value>
</property>
<property name="interceptorNames">
<list>
<value>jHasEvidHibernateInterceptor</value>
</list>
</property>
</bean>
Kde association je jakykoli parametr ktery ma byt jednoduse predan.
Lukas "benzin" Benda ([EMAIL PROTECTED]; http://benzin.bloguje.cz)
Java a Delphi programator
PHP a JavaScript skrypter
Tvurce databazovych aplikaci
A "cestinarsky" ignorant
Dobry den,
mam prosbu o pomoc:
Ve svem projektu pouzivam spring (1.2.6) a hibernate (3.1RC1) a
nefunguje mi lazy inicializace mapovanych objektu : tomcat pise chybu:
failed to lazily initialize a collection of role:
beans.Project.phases, no session or session was closed
konfigurace v msfchecklist-servlet.xml:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource" /></property>
<property
name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
<property
name="configurationClass"><value>org.hibernate.cfg.AnnotationConfiguration</value></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key=" hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Transactions -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"
/></property>
</bean>
<bean id="dataStorageTarget" class="
businesslogic.DataStorageFacadeImpl">
<property name="documentDAO" ref="documentDAO" />
<property name="documentInPhaseDAO" ref="documentInPhaseDAO" />
<property name="documentTypeDAO" ref="documentTypeDAO" />
<property name="phaseDAO" ref="phaseDAO" />
<property name="phaseInProjectDAO" ref="phaseInProjectDAO" />
<property name="projectDAO" ref="projectDAO" />
<property name="projectTypeDAO" ref="projectTypeDAO" />
<property name="roleDAO" ref="roleDAO" />
<property name="roleInProjectDAO" ref="roleInProjectDAO" />
<property name="signDAO" ref="signDAO" />
<property name="signRequestDAO" ref="signRequestDAO" />
<property name="userDAO" ref="userDAO" />
</bean>
<bean id="dataStorage"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref
local="transactionManager" /></property>
<property name="target"><ref local="dataStorageTarget"
/></property>
<property name="transactionAttributeSource">
<bean
class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"
/>
</property>
</bean>
Ve web.xml pouzivam:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>
OpenSessionInViewFilter by mel (podle me) zajistit, ze se bude
pouzivat jedina Session a jedina SessionFactory a cely pozadavek se
bude zpracovavat v jedine transakci.
Bohuzel se z nejakeho duvodu stane, ze hibernate mi session zavre,
takze kdyz pak zpracovavam nactene objekty v kontroleru, lazy
inicializace uz tam nefunguje.
Facada vypada takto:
@Transactional
public interface DataStorageFacade {
// -- Query methods
// -----------------------------------------------------------------
/**
* Return all projects in the database.
*
* @return all projects in the database.
*/
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public List<Project> getAllProjects();
/**
* Return all phases in the database.
*
* @return all phases in the database.
*/
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public List<Phase> getAllPhases();
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public List<ProjectType> getAllProjectTypes();
atd.
}
Snazil jsem se vysledovat, kde presne se ta session zavre a dosel jsem
tady:
org.springframework.orm.hibernate3.SessionFactoryUtils :
private static void closeSessionOrRegisterDeferredClose(Session
session, SessionFactory sessionFactory) {
Map holderMap = (Map) deferredCloseHolder.get();
if (holderMap != null && sessionFactory != null &&
holderMap.containsKey(sessionFactory)) {
logger.debug("Registering Hibernate Session for deferred
close");
Set sessions = (Set) holderMap.get(sessionFactory);
sessions.add (session);
if (!session.isConnected()) {
// We're running against Hibernate 3.1 RC1, where
Hibernate will
// automatically disconnect the Session after a
transaction.
// We'll reconnect it here, as the Session is likely
gonna be
// used for lazy loading during an "open session in
view" pase.
session.reconnect();
}
}
else {
doClose(session);
}
}
Z nejakeho duvodu je zde holderMap == null, takze se vola
doClose(session) a ta zavre session.
Diky za jakoukoli pomoc.
Standa