java - 防止同一个对象关联到 hibernate 中的两个不同 session

标签 java hibernate session

使用 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>

这是我的 session 过滤器:

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) {...

当通过 AJAX 同时重新渲染 UI 两次或更多次时,问题就来了。作为两个不同的请求,它们每个都有一个 Session,并且尝试将对象同时附加到它们两个,因为它们都没有足够的时间来完成和执行 session.close(),所以hibernate抛出异常 org.hibernate.HibernateException:非法尝试将一个集合与两个打开的 session 相关联

有什么建议可以防止这种情况发生吗?谢谢。

更新: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>

最佳答案

显然使用 merge 而不是 update 似乎可以解决问题...

记住 merge 返回新的更新实例,所以你应该这样做

myInstance = (myInstanceClass) Session.merge(myInstance);

关于java - 防止同一个对象关联到 hibernate 中的两个不同 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2280133/

相关文章:

java - Maven 插件注释的 IntelliJ 错误消息

java - 使用 .java 文件编译文件夹并将其打包

hibernate - 如何使用 Quarkus 和 Panache 在 snake case 中获取表名

java - Junit 忽略我在服务中的 @Transactional 注释

hibernate - 是否可以在 HQL 中覆盖 Hibernate 的 'like' 运算符?

java - 尝试在 Oreo 设备上创建新的 'Session' 对象时出现 fatal error

Java 网络爬虫看到验证码

session - Laravel session key 一直在改变?

PHP 总是创建一个新 session

java - 如何使用 Startapp 实现奖励视频