Struts2 + 完整的 Hibernate 插件 -->会话已关闭?
与这个问题相关(答案并没有真正切中要害):
Related to this question (where the answer doesn't really get to the point):
使用 Struts2 休眠- 使用完全休眠插件或其他方法关闭会话?
我有相同的设置:Struts 2.2.3 和 struts2-fullhibernatecore-plugin-2.2.2-GA .我没有更改 Struts2 和插件的默认值.我使用的是 MySQL,没有额外的连接池,一般来说没有什么花哨的.
I have the same setup: Struts 2.2.3 and the struts2-fullhibernatecore-plugin-2.2.2-GA . I have none of the defaults changed for Struts2 and for the Plugin. I'm using MySQL, no additional connection pooling, and nothing fancy in general.
我在我的操作中使用以下代码:
I use the following code in my Action:
FeedGroup persistent = null;
List<FeedGroup> list = objectList = (List<FeedGroup>) session.createCriteria(FeedGroup.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
if (feedgroup.getId() != 0) // a new one
{
persistent = (FeedGroup) session.get(FeedGroup.class, id);
}
if (persistent != null)
{
persistent.copyValuesFromOther(feedgroup);
session.update(persistent);
}
else
session.save(feedgroup);
return list;
这给了我以下异常大约每 10 次左右,这在我的代码中不会发生,但很可能在插件提交事务之后发生.
This gives me the following exception only in about every 10 cases or so, which doesn't happen in my code, but likely after the transaction got committed by the plugin.
org.hibernate.SessionException: Session is closed!
org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1346)
abelssoft.newspaper.actions.ActionHelper.prepare(ActionHelper.java:65)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:167)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:619)
是我的代码逻辑有问题还是插件相关的问题?如果是后者,配置更改是否有帮助?我想按原样使用插件,我只是担心它不能可靠地工作,或者我对数据库东西的理解太原始并且我的代码需要重写;-).
Is it a problem in the logic of my code or is it a problem related to the Plugin? If the latter, can a configuration change help? I'd like to use the plugin as it is, I'm just worried that it doesn't work reliably or that my understanding of Database stuff is too primitive and that my code needs rewriting ;-).
推荐答案
好的,由于没有人得到答案,我再次查看了问题和代码并搜索了一下.
Okay, as noone's got an answer, I looked into the question and the code again and googled a bit.
事实 1:该插件只支持到 Struts 2.1.6,另外我正在使用新的 Tomcat 7,所以我猜想该插件可能无法正常工作.
Fact 1: The plugin is only supported till Struts 2.1.6, additionally I'm using the new Tomcat 7, so I guessed that something might just not work with the plugin.
事实 2:Hibernate 论坛中的某个人指出,如果您尝试访问会话而不是打开一个新会话,就会出现此问题:Hibernate 论坛:Session is Closed!(靠近底部的解决方案)
Fact 2: Someone in a Hibernate Forum pointed out, that this problem can arise if you try to access the session instead of opening a new one: Hibernate Forum:Session is Closed! (solution near the bottom)
似乎事实 1 导致 @session
和 @transaction
的注释无法正常工作,或者我使用错误,因为它们在我的prepare 方法,就是这样一个类,我所有的 struts2 动作都是从它派生的:
It seem that fact 1 lead to the Annotations of @session
and @transaction
not working correctly, or I was using them wrong, as they were often null in my prepare method, which is such a class and from which all my struts2 actions are derived:
public abstract class ActionHelper extends ActionSupport implements Preparable, ...
在本课程中,我使用了以下通常在迄今为止所有其他项目(Struts 2.1.6 和 Tomcat 6)中都有效的注解:
In this class, I used the following Annotations that usually worked in all other projects so far (Struts 2.1.6 and Tomcat 6):
@SessionTarget
Session db;
@TransactionTarget
Transaction transaction;
private FeedGroupDAO _feedGroupDao;
在 prepare 方法中,我有防御性编程代码检查会话是否为空,然后将其替换为当前的休眠会话.问题是这个会话经常被关闭,如果你问 if (!session.isOpen())
In the prepare method, I had defensive programming code that checked if the session was null and then replaced it by the current hibernate session. The problem was that this session was often times closed, what you can find out if you ask if (!session.isOpen())
因此,现在我在 ActionHelper 类的 prepare 方法中使用以下代码:
Therefore now I use the following code in my prepare method in the ActionHelper class:
public void prepare() throws Exception {
// initialize DAO Objects with Session and Transaction
if (session == null)
{
session = com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getNewSession();
if (!session.isOpen())
throw new NullPointerException("Fix the code: session's not here");
transaction = session.beginTransaction();
}
_feedGroupDao = new FeedGroupDAO(session,transaction); // init more DAOs with the same session/transaction
插件的 getNewSession()
方法似乎在内部使用了 Hibernate 的 openSession()
,因此这似乎是来自 Hibernate-forums 的有效解决方案.此外,它仍然支持 OpenSessionInView 模式,因为 struts2-fullhibernate-plugin 正在管理您从静态 getNewSession()
方法获得的会话和事务.作为旁注,我尝试从防御性编程转向尽快抛出异常;-)
The getNewSession()
method of the plugin seems to use Hibernate's openSession()
internally, therefore this seems to be the working solution from the Hibernate-forums. Additionally, this still supports the OpenSessionInView pattern as the struts2-fullhibernate-plugin is managing the session and transaction you got from the static getNewSession()
method. As a sidenote, I try to move away from defensive programming to throwing exceptions as soon as possible ;-)
希望这对你有帮助.
相关文章