简体   繁体   English

org.hibernate.AssertionFailure:可能对会话进行非线程安全的访问

[英]org.hibernate.AssertionFailure: possible non-threadsafe access to the session

I am developing a web application with AngularJs as front-end and Spring+Hibernate as the service layer.我正在开发一个以 AngularJs 作为前端和 Spring+Hibernate 作为服务层的 Web 应用程序。 Service Layer has a set of REST API's that are consumed by AngularJs.服务层有一组由 AngularJs 使用的 REST API。 The front end of the application has no major issues.应用程序的前端没有大问题。 But in the service layer, I am facing some concurrency issues.但是在服务层,我面临一些并发问题。 For some scenarios, I have to make parallel Asychronous calls to same REST API's from the same http session.对于某些情况,我必须从同一个 http 会话对同一个 REST API 进行并行异步调用。 When I do that, there are times when I get the above error.当我这样做时,有时会出现上述错误。 Actually, the error keeps of changing everytime.实际上,错误每次都在不断变化。 Sometimes I also get NULLPointerException on Query.List() operation.有时我也会在 Query.List() 操作上得到 NULLPointerException。 Sometimes I get TransactionResourceAlreadyClosed exception.有时我会收到 TransactionResourceAlreadyClosed 异常。 Various configurations and code snippets are attached below.下面附上各种配置和代码片段。

Web.xml网页.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/config/fs-cxf-serverContext.xml,WEB-INF/config/fs-spring-jpa-config.xml,WEB-INF/config/security-beans.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.origins</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.headers</param-name>
        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin</param-value>
    </init-param>
    <init-param>
        <param-name>cors.exposed.headers</param-name>
        <param-value>Access-Control-Allow-Origin</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.methods</param-name>
        <param-value>GET, POST, PUT, DELETE, OPTIONS, HEAD</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<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>
</filter-mapping>

<servlet>
    <description>Servlet to Initialize and shutdown the Scheduler</description>
    <servlet-name>QuartzInitializer</servlet-name>
    <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
    <init-param>
        <param-name>config-file</param-name>
        <param-value>quartz.properties</param-value>
    </init-param>
    <init-param>
        <param-name>shutdown-on-unload</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>start-scheduler-on-load</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

<resource-ref>
    <res-ref-name>jdbc/foodsafetyDS</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

JPA Configuration JPA 配置

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

<!-- Hibernate session factory -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
    <property name="entityInterceptor">
        <bean class="com.cts.foodSafety.interceptor.AuditLogInterceptor"/>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="persistenceAnnotation"
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<tx:annotation-driven transaction-manager="transactionManager" />
<task:annotation-driven/>

Hibernate.cfg.xml休眠文件.cfg.xml

<hibernate-configuration>
<session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.datasource">java:comp/env/jdbc/foodsafetyDS</property>
    <property name="hbm2ddl.auto">update</property>
    <property name="show_sql">false</property>

    <!-- Mapping with model class containing annotations -->

I have created a simple rest controller using CXF.我使用 CXF 创建了一个简单的休息控制器。 REST end point is as below REST端点如下

@Path("/units")
@Produces(MediaType.APPLICATION_JSON)
public interface UnitService extends Serializable {

@GET
@Path("/getGraphData/{type}")
@Produces(MediaType.APPLICATION_JSON)
public UnitServiceBean getGraphData(@PathParam("type") String type)
        throws FoodSafetyException;

} }

Implementation of the controller is as below控制器的实现如下

xxxServiceImpl.java xxxServiceImpl.java

@Service("unit")
@Transactional
public class xxxServiceImpl implements xxxService {

private static final long serialVersionUID = 1L;

@Autowired
xxxDelegate xxxDelegate;

@Override
public UnitServiceBean getGraphData(String type) throws FoodSafetyException {
    UnitServiceBean bean = new UnitServiceBean();

    List<String[]> data = unitDelegate.getGraphData(type);
    ....
    ....
    return bean;
}

Delegate calls the DAO.委托调用 DAO。 (We haven't introduced the Business object as of now). (到目前为止,我们还没有引入 Business 对象)。 Implementation of DAO is as below DAO的实现如下

@Component
public class UnitDAOImpl extends FoodSafetyDAO implements UnitDAO {
@Override
public List<String[]> getGraphData(String type) {
    List<String[]> data = new ArrayList<String[]>();
    Map<String, List<UnitReadingEntity>> readings = new HashMap<String, List<UnitReadingEntity>>();

    SimpleDateFormat df = CommonConstants.TIME_FORMATTER;

    // Get all the Units
    Query query = getSession().getNamedQuery(
            QueryConstants.FIND_UNITS_BY_TYPE);
    query.setParameter(QueryConstants.TYPE, type);
    List<UnitEntity> units = (List<UnitEntity>) query.list();
    if (units != null && units.size() != 0) {
        .....
        .....

        for (UnitEntity unit : units) {
            Calendar cal1 = Calendar.getInstance();
            cal1.add(Calendar.DAY_OF_YEAR, -1);
            query = getSession().getNamedQuery(
                    QueryConstants.FIND_READING_BY_UNIT_TIME).setLong(
                    QueryConstants.UNIT_ID, unit.getUnitId());

            List<UnitReadingEntity> rr = query.list();
            ...
            ...
        }
    }

    return data;
}

Now, when I call the REST service "getGraphData" once using POSTMAN etc. it works fine without any issue.现在,当我使用 POSTMAN 等调用 REST 服务“getGraphData”时,它工作正常,没有任何问题。 But when I simulate concurrent call to this rest service using I get following error但是,当我使用模拟并发调用此休息服务时,出现以下错误

Caused by: org.hibernate.AssertionFailure: possible non-threadsafe access to the session
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:130)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1108)
at org.hibernate.loader.Loader.processResultSet(Loader.java:964)
at org.hibernate.loader.Loader.doQuery(Loader.java:911)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342)
at org.hibernate.loader.Loader.doList(Loader.java:2526)
at org.hibernate.loader.Loader.doList(Loader.java:2512)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2342)
at org.hibernate.loader.Loader.list(Loader.java:2337)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:356)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1269)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at com.cts.foodSafety.model.dao.impl.UnitDAOImpl.getGraphData(UnitDAOImpl.java:255)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy51.getGraphData(Unknown Source)
at com.cts.foodSafety.delegate.UnitDelegate.getGraphData(UnitDelegate.java:39)
at com.cts.foodSafety.delegate.UnitDelegate$$FastClassByCGLIB$$aac35d0d.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.cts.foodSafety.delegate.UnitDelegate$$EnhancerByCGLIB$$75af66.getGraphData(<generated>)
at com.cts.foodSafety.service.impl.UnitServiceImpl.getGraphData(UnitServiceImpl.java:108)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:42)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy72.getGraphData(Unknown Source)
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.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)

Client that I used to make concurrent request is as below我用来发出并发请求的客户端如下

public class RestClient implements Runnable{

private String i;

public RestClient(String x) {
    i=x;
}
public static void main(String[] args) {

    for(int i =1;i<=2;i++) {
        Thread t = new Thread(new RestClient(String.valueOf(i)));
        t.start();
    }
}

@Override
public void run() {
    System.out.println("started " + i);
      try {

            URL url = new URL(" http://localhost:8080/fs/services/units/getGraphData/Freezer");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            if (conn.getResponseCode() != 204) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + conn.getResponseCode());
            }

Any pointers/suggestions ?任何指示/建议? I have gone through a lot of material on sessions and transaction management in Spring+hibernate.我在 Spring+hibernate 中浏览了很多关于会话和事务管理的材料。 But I am not able to get my head around this problem.但我无法解决这个问题。

I think, that if you use Hibernate like that, then you should acquire the session by calling getSession(false) instead so as to ensure you have the session bound to the transaction.我认为,如果您像这样使用 Hibernate,那么您应该通过调用getSession(false)来获取会话,以确保您将会话绑定到事务。

This is explained in chapter Implementing Spring-based DAOs without callbacks in Spring documentation : such code will usually pass false as the value of the getSession(..) methods allowCreate argument, to enforce running within a transaction (which avoids the need to close the returned Session, as its lifecycle is managed by the transaction).在 Spring 文档中的在没有回调的情况下实现基于 Spring 的 DAO一章中进行了解释:此类代码通常将传递 false 作为 getSession(..) 方法的值 allowCreate 参数,以强制在事务中运行(这避免了关闭返回会话,因为其生命周期由事务管理)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JSON 映射问题:可能对 session 进行非线程安全访问 - JSON mapping problem: possible non-threadsafe access to the session HibernateCursorItemReader获取对会话错误的非线程安全访问 - HibernateCursorItemReader gets non-threadsafe access to the session Error org.hibernate.AssertionFailure 获取序列值时的问题 - org.hibernate.AssertionFailure Issue when getting sequence value org.hibernate.AssertionFailure: null 标识符@OneToOne 关系 - org.hibernate.AssertionFailure: null identifier @OneToOne relationship org.hibernate.AssertionFailure:集合被flush()处理了两次 - org.hibernate.AssertionFailure: collection was processed twice by flush() org.hibernate.criteria.uniqueResult期间的AssertionFailure - org.hibernate.AssertionFailure during criteria.uniqueResult Spring JPA/Hibernate org.hibernate.AssertionFailure: null id in Entity(异常发生后不刷新Session) - Spring JPA/Hibernate org.hibernate.AssertionFailure: null id in Entity (don't flush the Session after an exception occurs) Hibernate:org.hibernate.AssertionFailure:com.xxx.Bean条目中的null id - Hibernate: org.hibernate.AssertionFailure: null id in com.xxx.Bean entry Spring JPA 共享主键导致 org.hibernate.AssertionFailure: null identifier - Spring JPA Shared primary key causes org.hibernate.AssertionFailure: null identifier Hibernate 断言失败 - Hibernate AssertionFailure
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM