Spring 接管 Hibernate 配置 延迟加载(总结)
Spring配置延迟加载
两种方法:
1. 使用Spring提供的Open Session In View机制,它有两种配置方式OpenSessionInViewInterceptor和OpenSessionInViewFilter,功能相同,只是一个在web.xml配置,另一个在application.xml配置而已。
Open Session In View在request把session绑定到当前thread期间一直保持hibernate session在open状态,使session在request的整个期间都可以使用,如在View层里PO也可以lazy loading数据,如 ${ company.employees }。当View 层逻辑完成后,才会通过Filter的doFilter方法或Interceptor的postHandle方法自动关闭session。
a. 在web.xml中配置,使用OpenSessionInViewFilter过滤URL
1. <filter>
2. <filter-name>hibernateFilter</filter-name>
3. <filter-class>
4. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
5. </filter-class>
6. </filter>
7. <filter-mapping>
8. <filter-name>hibernateFilter</filter-name>
9. <url-pattern>/*</url-pattern>
10. </filter-mapping>
b. 在application.xml配置,使用OpenSessionInViewInterceptor过滤URL
1. <bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
2. <property name="sessionFactory">
3. <ref bean="sessionFactory"/>
4. </property>
5. </bean>
6. <bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
7. <property name="interceptors">
8. <list>
9. <ref bean="openSessionInViewInterceptor"/>
10. </list>
11. </property>
12. <property name="mappings">
//配置需要过滤的URL
13. </property>
14. </bean>
2. 通过在 Spring 应用程序上下文中的一些配置,我们可以让将调用 serviceProxy的方法拦截下来,再令它的方法支持延迟加载。当 serviceProxy被调用的时候, HibernateInterceptor 打开一个 Hibernate 会话,并将调用请求传递给 service对象。当 service执行完成后, HibernateInterceptor 透明地关闭了会话。应用层的代码不用了解任何持久层逻辑,还是实现了延迟加载。
1. <bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
2. <property name="sessionFactory" ref="sessionFactory"/>
3. </bean>
4. //配置对于的service例如配置Service
5. <bean id="service"
class="xx.xxx.xxx.Service">
6. <property name="xxxDao" ref="XXXDao"/>
7. </bean>
8. //配置代理
9. <bean id="serviceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
10. <property name="target">
11. <ref bean="service"/>
12. </property>
13. <property name="proxyInterfaces">
14. <value>对于的service的接口</value>
15. </property>
16. <property name="interceptorNames">
17. <list>
18. <value>hibernateInterceptor</value>
19. </list>
20. </property>
21. </bean>
在单元测试中测试延迟加载
需要用 J-Unit 来测试我们的延迟加载程序。我们可以轻易地通过重写 TestCase 类中的 setUp 和 tearDown 方法来实现这个要求。
1. import junit.framework.TestCase;
2. import org.hibernate.Session;
3. import org.hibernate.SessionFactory;
4. import org.springframework.orm.hibernate3.SessionFactoryUtils;
5. import org.springframework.orm.hibernate3.SessionHolder;
6. import org.springframework.transaction.support.TransactionSynchronizationManager;
7. public abstract class MyLazyTestCase extends TestCase {
8. private SessionFactory sessionFactory;
9. private Session session;
10. public void setUp() throws Exception {
11. super.setUp();
12. SessionFactory sessionFactory =
13. (SessionFactory) getBean("sessionFactory");
14. session = SessionFactoryUtils.getSession(sessionFactory, true);
15. Session s = sessionFactory.openSession();
16. TransactionSynchronizationManager.bindResource(sessionFactory,
new SessionHolder(s));
17. }
18. protected Object getBean(String beanName) {
19. //Code to get objects from Spring application context
20. return null;
21. }
22. public void tearDown() throws Exception {
23. super.tearDown();
24. SessionHolder holder =
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
25. Session s = holder.getSession();
26. s.flush();
27. TransactionSynchronizationManager.unbindResource(sessionFactory);
28. SessionFactoryUtils.closeSession(s);
29. }
30. }