这与Spring 在服务层上OpenSessionInViewFilter使用 @Transactional注释有关。
OpenSessionInViewFilter
@Transactional
我经历了很多关于此的堆栈溢出问题,但是仍然对是否应该OpenSessionInViewFilter避免使用感到困惑。LazyInitializationException 如果有人帮助我找出以下查询的答案,那将是很大的帮助。
LazyInitializationException
N+1
下面是我的Spring配置文件
<context:component-scan base-package="com.test"/> <context:annotation-config/> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="resources/messages" /> <property name="defaultEncoding" value="UTF-8" /> </bean> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="/WEB-INF/jdbc.properties" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <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">${jdbc.dialect}</prop> <prop key="hibernate.show_sql">true</prop> <!-- <prop key="hibernate.hbm2ddl.auto">create</prop> --> </props> </property> </bean> <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
OpenSessionInView是一个servlet过滤器,而不仅仅是打开一个hibernate会话,并将其存储在SessionHolder服务请求的线程中。打开此会话后,在请求的呈现阶段使用hibernate时,它可以读取Lazy初始化的集合和对象。调用时可以访问此会话SessionFactory.getCurrentSession()。
OpenSessionInView
SessionHolder
SessionFactory.getCurrentSession()
但是,OpenSessionInView只会打开会话,并且不会开始任何事务。在打开会话的情况下,您可以从数据库中读取对象,但是,如果要在事务中执行某些操作,则需要@Transactional注释或其他机制来在需要时划定事务的开始和结束位置。
然后是问题的答案:
在具有复杂模式的应用程序中使用OpenSessionInViewFilter是不好的做法。
如果您需要避免LazyInitializationException并且重载只是打开新的Hibernate Session并在每个请求的请求结束时将其关闭,则这是一个好习惯。
使用此滤镜可能会导致N + 1问题
我在许多项目中都使用了此过滤器,并且不会引起任何问题。
如果我们使用的是OpenSessionInViewFilter,是否意味着不需要@Transactional?
不会。您只能在线程的SessionHolder中打开一个Hibernate Session,但是如果需要Transaction,则需要put @Transactional。