使用jsf 1.2,hibernate,richfaces 3.3.0GA和facelets。
我在我的支持bean中有这个代码:
public List<Rater> getFreeRaters(){
GP myGP = (GP) user;
update(myGP.getContract());
ArrayList<Rater> raters = new ArrayList<Rater>(myGP.getContract().getRaters());
ArrayList<Rater> selectedRaters = this.getSelectedRaters();
raters.removeAll(selectedRaters);
return raters;
}
和UI的这段代码:
<a4j:form id="gradersForm" ajaxSingle="true">
<rich:listShuttle sourceValue="#{user.gradersTab.freeRaters}" id="gradersTab_listShuttle"
targetValue="#{user.gradersTab.selectedRaters}" var="rater" listsHeight="150"
sourceListWidth="130" targetListWidth="130" sourceCaptionLabel="Available Items"
targetCaptionLabel="Currently Active Items" >
<rich:column>
<h:outputText value="#{rater.username}"></h:outputText>
</rich:column>
</rich:listShuttle>
<a4j:commandButton value="Save"></a4j:commandButton>
</a4j:form>
这是我的会话过滤器:
public class HibernateSessionRequestFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);
private SessionFactory sf;
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletResponse resp= (HttpServletResponse) response;
try {
log.info("Starting a database transaction");
Session session = sf.getCurrentSession();
session.beginTransaction();
// Call the next filter (continue request processing)
chain.doFilter(request, resp);
// Commit and cleanup
log.info("Committing the database transaction");
session.getTransaction().commit();
} catch (StaleObjectStateException staleEx) {...
当UI通过AJAX同时重新渲染两次或更多时,问题就出现了。作为两个不同的请求,每个请求获得Session
,并且试图同时将对象附加到它们两者,因为它们都没有时间完成并且session.close()
,所以hibernate抛出一个异常
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
有任何建议可以防止这种情况发生吗?感谢。
更新:web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
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_2_5.xsd">
<display-name>eyeprevent</display-name>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/functions.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>#{user.skin}</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>
<filter>
<filter-name>HibernateFilter</filter-name>
<filter-class>com.eyeprevent.util.HibernateSessionRequestFilter</filter-class>
</filter>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>HibernateFilter</filter-name>
<url-pattern>/pages/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HibernateFilter</filter-name>
<url-pattern>/upload/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<listener>
<listener-class>com.eyeprevent.util.MySessionListener</listener-class>
</listener>
<servlet>
<display-name>EPConnectServlet</display-name>
<servlet-name>EPConnectServlet</servlet-name>
<servlet-class>com.eyeprevent.servlets.EPConnectServlet</servlet-class>
<init-param>
<param-name>imagePath</param-name>
<param-value>/home/pako/images</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>imageServlet</servlet-name>
<servlet-class>com.eyeprevent.servlets.ImageServlet</servlet-class>
<init-param>
<param-name>imagePath</param-name>
<param-value>/home/pako/images</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>EPConnectServlet</servlet-name>
<url-pattern>/upload/EPConnectServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>imageServlet</servlet-name>
<url-pattern>/image/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>0</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.xhtml</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>pages/login.xhtml</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/pages/error.xhtml</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/pages/unauthorized.xhtml</location>
</error-page>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
答案 0 :(得分:2)
显然使用merge
代替update
似乎可以解决问题...
请记住,merge
会返回新更新的实例,因此您应该
myInstance = (myInstanceClass) Session.merge(myInstance);