java – Spring,@Transactional和Hibernate Lazy Loading
我正在使用春天的冬眠.我所有的HibernateDAO直接使用sessionFactory.
我有应用层 – >服务层 – > DAO层和所有的集合都是加载的. 所以,问题是在应用程序层(包含GUI / swing)的某个时刻,我使用服务层方法(包含@Transactional注释)加载一个实体,我想使用这个对象的一个??惰性属性,但是可以直观地看到会话已经关闭 解决这个麻烦的最好办法是什么? 编辑 我尝试使用MethodInterceptor,我的想法是为所有实体编写一个AroundAdvice,并使用注释,例如: // Custom annotation,say that session is required for this method @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface SessionRequired { // An AroundAdvice to intercept method calls public class SessionInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation mi) throws Throwable { bool sessionRequired=mi.getMethod().isAnnotationPresent(SessionRequired.class); // Begin and commit session only if @SessionRequired if(sessionRequired){ // begin transaction here } Object ret=mi.proceed(); if(sessionRequired){ // commit transaction here } return ret; } } // An example of entity @Entity public class Customer implements Serializable { @Id Long id; @OneToMany List<Order> orders; // this is a lazy collection @SessionRequired public List<Order> getOrders(){ return orders; } } // And finally in application layer... public void foo(){ // Load customer by id,getCustomer is annotated with @Transactional // this is a lazy load Customer customer=customerService.getCustomer(1); // Get orders,my interceptor open and close the session for me... i hope... List<Order> orders=customer.getOrders(); // Finally use the orders } 你认为这可以工作吗? 解决方法
Hibernate最近推出了提取配置文件(除了性能调优之外)是解决这类问题的理想选择.它允许您(在运行时)在不同的加载和初始化策略之间进行选择.
http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-fetching-profiles 编辑(添加了关于如何使用拦截器设置抓取配置文件的部分): 开始之前:检查抓取的个人资料实际上是否适合您.我没有自己使用它们,看到他们目前仅限于加入提取.在浪费时间实施和接线拦截器之前,请尝试手动设置抓取配置文件,看到它实际上可以解决您的问题. 有很多方法可以在Spring中设置拦截器(根据偏好),但最直接的方法是实现一个MethodInterceptor(见http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api.html#aop-api-advice-around).让它有一个设置器为您要获取的配置文件和设置为休眠会话工厂: public class FetchProfileInterceptor implements MethodInterceptor { private SessionFactory sessionFactory; private String fetchProfile; ... setters ... public Object invoke(MethodInvocation invocation) throws Throwable { Session s = sessionFactory.openSession(); // The transaction interceptor has already opened the session,so this returns it. s.enableFetchProfile(fetchProfile); try { return invocation.proceed(); } finally { s.disableFetchProfile(fetchProfile); } } } 最后,在Spring配置中启用拦截器.这可以通过几种方式完成,您可能已经有一个可以将其添加到的AOP设置.见http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-schema. 如果您是AOP的新手,建议先尝试使用“旧”ProxyFactory方式(http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api .html#aop-api-proxying-intf),因为它更容易理解它是如何工作的.以下是一些示例XML,让您开始: <bean id="fetchProfileInterceptor" class="x.y.zFetchProfileInterceptor"> <property name="sessionFactory" ref="sessionFactory"/> <property name="fetchProfile" ref="gui-profile"/> </bean> <bean id="businessService" class="x.y.x.BusinessServiceImpl"> <property name="dao" .../> ... </bean> <bean id="serviceForSwinGUI" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="x.y.z.BusinessServiceInterface/> <property name="target" ref="businessService"/> <property name="interceptorNames"> <list> <value>existingTransactionInterceptorBeanName</value> <value>fetchProfileInterceptor</value> </list> </property> </bean> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |