您使用什么样的替代策略来避免LazyLoadExceptions?
我确实理解在视图中打开会话有以下问题:
但是,如果您知道您的应用程序在单个虚拟机上运行,为什么不通过在视图策略中使用开放会话来减轻您的痛苦?
我的目标是在从Hibernate生成HTTP响应时实现O(1)空间复杂度ScrollableResults.我想保留MessageConverter调度a的标准机制来处理从a返回的对象@Controller.我已经设置了以下内容:
MappingJackson2HttpMessageConverter丰富了JsonSerializer处理Java 8的a Stream;ScrollableResultSpliterator包装需要ScrollableResults成Stream;OpenSessionInViewInterceptor需要保持Hibernate会话在MessageConverter;hibernate.connection.release_mode为ON_CLOSE;con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT).另外,我需要一个支持这种可保持性的数据库.PostgreSQL就是这样一个数据库,我对此没有任何麻烦.
我遇到的最后一个绊脚石是HibernateTransactionManager事务提交所使用的策略:除非底层会话是"Hibernate管理的",否则它会disconnect()关闭我的光标以及其他所有内容.这样的策略在某些特殊情况下很有用,特别是"会话范围会话",这些会议远离我的要求.
我设法用一个糟糕的黑客解决这个问题:我不得不用一种方法来覆盖有问题的方法,该方法实际上是原始的复制粘贴,除了被移除的disconnect()调用,但它必须求助于反射来访问私有API.
public class NoDisconnectHibernateTransactionManager extends HibernateTransactionManager
{
private static final Logger logger = LoggerFactory.getLogger(NoDisconnectHibernateTransactionManager.class);
public NoDisconnectHibernateTransactionManager(SessionFactory sf) { super(sf); }
@Override
protected void doCleanupAfterCompletion(Object transaction) {
final JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) transaction;
final Class<?> c = …Run Code Online (Sandbox Code Playgroud) 我想配置OpenSessionInViewFilter为能够在视图中使用hibernate延迟初始化,所以我在web.xml中添加了过滤器定义,但它不起作用我仍然得到相同的延迟初始化异常,这是我做的:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>MyApp</display-name>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/spring/applicationContext.xml
classpath:META-INF/spring/applicationSecurity.xml
</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping> …Run Code Online (Sandbox Code Playgroud) 我在Tomcat上使用Hibernate和Spring.我一直在阅读并重新阅读关于该主题的指向JBoss wiki页面的内容,这很有帮助.但它给我留下了一些问题.
为每个请求启动交易的想法让我很烦恼.我想我可以将过滤器限制在某些控制器 - 可能将我需要交易的所有控制器放在伪"tx"路径下.但如果您不知道是否需要交易,那么使用交易不是一个坏主意吗?如果我只是在某些请求中读取 - 很可能来自缓存的读取 - 在没有事务的情况下我不是更好吗?
我读过帖子,提到他们如何处理服务层的事务,我想用Spring做这件事.但那么过滤器代码是什么样的呢?我仍然希望在我的视图中可以使用会话进行一些延迟加载.
如果我所要做的就是调用sessionFactory.getCurrentSession()我的过滤器,它如何被"释放"回会话工厂重新使用?(session.close()即使在使用事务时,我也希望看到一个或者什么.)谁在告诉会话工厂该会话可以重用?
也许beginTransaction()是在请求期间将给定数据库连接绑定到给定会话的调用?否则,会话根据需要从池中提取数据库连接,对吧?
感谢您对我的所有问题的耐心等待.
(如果你的答案将成为Spring文档的链接,那么你只会让我哭泣.你不想要那个,是吗?如果人们不再回答Spring相关的问题,我会付真钱吗办法.)
在一个相对较大的 Spring Boot 项目中,我有一个具有以下(过于简化的)事件序列的方法:
Car car = carRepository.save(new Car());
Person person = personRepository.save(new Person(car)); // Car is a field of Person
Engine engine = engineRepository.save(new Engine());
person.getCar().setEngine(engine);
carRepository.save(person.getCar()); // without this the engine and car relation is not registered
Run Code Online (Sandbox Code Playgroud)
Car、Person和Engine都是@Entity类(数据库对象)。对于这个例子,它们的实现可能如下:
// Car.java
@Entity
@Table(name = "car_tbl")
public class Car {
@Id
@GeneratedValue
@Column(name = "car_id")
private Long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "engine_id", unique = true)
private Engine engine;
}
// Person.java …Run Code Online (Sandbox Code Playgroud) 我似乎在Spring/MVC 3.0/Hibernate 3.5应用程序中随机获取以下LazyInitializationException,尽管看到堆栈跟踪中的过滤器本身.关于我应该研究什么的任何想法?
07 Jun 2011 13:48:47,152 [ERROR] (http-3443-2) org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.test.Image_$$_javassist_18.getMyKey(Image_$$_javassist_18.java)
at com.test.AppTagHelper.getAssetUrl(AppTagHelper.java:66)
at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstFunction.getValue(AstFunction.java:110)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:935)
at org.apache.jsp.WEB_002dINF.view.home_jsp._jspx_meth_c_005fout_005f2(home_jsp.java:1027)
at org.apache.jsp.WEB_002dINF.view.home_jsp._jspx_meth_c_005fwhen_005f1(home_jsp.java:1002)
at org.apache.jsp.WEB_002dINF.view.home_jsp._jspx_meth_c_005fchoose_005f1(home_jsp.java:969)
at org.apache.jsp.WEB_002dINF.view.home_jsp._jspx_meth_display_005fcolumn_005f0(home_jsp.java:867)
at org.apache.jsp.WEB_002dINF.view.home_jsp._jspService(home_jsp.java:214)
<<VARIOUS SPRING FILTERS>>
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
Run Code Online (Sandbox Code Playgroud)
来自web.xml:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping> …Run Code Online (Sandbox Code Playgroud) 我正在使用Hibernate的延迟加载,并且在将OpenSessionInViewFilter添加到我的web.xml之后,即使在定义要使用的sessionFactory bean之后,我也开始使sessionFactory失去异常.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory' is defined
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1097)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:242)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:227)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:171)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
Run Code Online (Sandbox Code Playgroud)
这似乎是同样的问题,但不幸的是我不明白解决方案.我按照建议的解决方案(将sessionFactory移动到一个名为root-spring.xml的文件)我得到了服务器启动的例外.
知道我错过了什么吗?
web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>recommendationCrawler</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--<listener>-->
<!--<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>-->
<!--</listener>-->
<!--<context-param>-->
<!--<param-name>log4jConfigLocation</param-name>-->
<!--<param-value>/WEB-INF/log4j.properties</param-value>-->
<!--</context-param>-->
<!-- listener to load the root application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Run Code Online (Sandbox Code Playgroud)
为spring-servlet.xml
<?xml version="1.0" …Run Code Online (Sandbox Code Playgroud) 当我尝试在 Tomcat7 中启动 Java EE Spring+Hibernate 应用程序时,出现异常。这曾经有效,但我想我在迁移到 Tomcat7 时搞砸了一些事情。例外的是
Mar 29, 2013 11:38:33 PM org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter hibernateFilter
java.lang.ClassCastException: org.springframework.orm.hibernate3.support.OpenSessionInViewFilter cannot be cast to javax.servlet.Filter
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:248)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:368)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:98)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4193)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4801)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:988)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:771)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:988)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:275)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:427)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:649)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
at org.apache.catalina.startup.Catalina.start(Catalina.java:585)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:415)
Mar 29, 2013 11:38:33 PM …Run Code Online (Sandbox Code Playgroud) hibernate ×8
spring ×5
java ×4
exception ×1
java-8 ×1
jpa ×1
lazy-loading ×1
servlet-3.0 ×1
spring-boot ×1
spring-orm ×1