我们使用 Hibernate(带有 JPA)和 Hibernate Envers 来保存对象的历史记录。 Web 应用程序运行许多线程,其中一些是由其他应用程序调用 RMI 方法创建的,一些是由应用程序本身创建的,还有一些是为处理 http 请求(它们生成 View )而创建的。
我们还使用 Open Session In View 模式来管理 session ,因此我们的 web.xml 包含:
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
数据库是使用 DAO 访问的,它们都具有由 Spring 注入(inject)的 EntityManagers。
@PersistenceContext
protected EntityManager em;
@PersistenceUnit
protected EntityManagerFactory emf;
在我们决定使用 Hibernate Envers 之前,一切都运行良好。当任何不是 View 生成线程的线程运行代码以获取对象的旧版本时,将抛出异常。
@Override
public O loadByRevision(Long revision, Long id) {
@SuppressWarnings("unchecked")
O object = (O) AuditReaderFactory.get(em).createQuery().forEntitiesAtRevision(getBaseClass(), revision.intValue())
.add(AuditEntity.id().eq(id)).getSingleResult();
return object;
}
Exception in thread "Scheduler" org.hibernate.SessionException: Session is closed! at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:129) at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1776) at org.hibernate.envers.tools.query.QueryBuilder.toQuery(QueryBuilder.java:226) at org.hibernate.envers.query.impl.AbstractAuditQuery.buildQuery(AbstractAuditQuery.java:92) at org.hibernate.envers.query.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:108) at org.hibernate.envers.query.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:110) (...)
当上面的代码由 View 生成线程运行时,它工作正常。此外,DAO 中的非 envers 代码适用于每个线程。例如,下面的片段
@Override
public O load(Long id) {
final O find = em.find(getBaseClass(), id);
return find;
}
可以由 RMI 线程毫无问题地运行。
为什么非 View 线程可以毫无异常(exception)地调用实体管理器上的方法,但不能将 Envers 的 AuditReaderFactory 与该实体管理器一起使用?我认为也许在实体管理器上调用一个方法会创建一个临时 session ,但在使用 Envers 时不会发生这种情况,是这样吗?
解决该问题的最佳方法是什么(以便每个线程都可以使用 AuditReaderFactory)?
最佳答案
我们没有发现为什么在非 ui 线程中对 EntityManagerFactory 的方法调用有效,但对 AuditReaderFactory 的方法调用却没有。不管怎样,我们找到了修复它的方法。
解决方案是使用 @Transactional 注释方法。如果在调用 AuditReaderFactory 之前调用链中的任何方法被标记为 @Transactional,则非 ui 线程中没有 SessionException。
事实证明,使 loadByRevision 具有事务性是不够的。如果该方法返回的对象包含延迟加载的持久包,则在 loadByRevision 方法范围之外访问它们会导致 LazyInitializationException(没有 session )。
最终的解决方案是确保如果任何线程想要从数据库加载一些数据,所有加载(获取对象和访问延迟加载的集合)都将在一个用 @Transactional 注释的方法中完成。
关于java - Spring + Hibernate + Envers + 多线程 - session 关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21023989/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/