压力测试中的Hibernate并发修改异常问题

hi3rlvi2  于 2023-03-03  发布在  其他
关注(0)|答案(1)|浏览(156)

There is an application with the following configuration:
1- HK2 for DI
2- Hibernate for ORM
and
3- GrizzlyHttpServer
and the its hibernate configuration is :

import org.hibernate.*;
import org.hibernate.boot.*;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.jvnet.hk2.annotations.Service;

@Service
public class HibernateOracle {
    private Session session;
    private SessionFactory factory;

    public HibernateOracle() {
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure() // configures settings from hibernate.cfg.xml
                .build();
        factory = new MetadataSources(registry).addPackage("com.art.entity").buildMetadata().buildSessionFactory();
        session = factory.openSession();
    }

    public Session getSession() {
        if (session == null || !session.isOpen())
            session = factory.openSession();
        return this.session;
    }

}

and the one method of a repository file is:

@jakarta.inject.Inject
private HibernateOracle hibernateOracle;

@Override
    public User get(String username) throws UserNotFoundException {
        Session session = hibernateOracle.getSession();
        try {
            return (User) session.createNamedQuery("User.findOneByUserName")
                    .setParameter("username", username).getSingleResult();
        } catch (Exception e) {
            e.printStackTrace();
            throw new UserNotFoundException();
        } finally {
            //
        }
    }

It is worked correctly in the normal state but when the application is tested by such as load-test the following exception is raised in this method:
java.util.ConcurrentModificationException at java.base/java.util.HashMap.forEach(HashMap.java:1424) at org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.releaseResources(ResourceRegistryStandardImpl.java:328) at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.afterTransaction(AbstractLogicalConnectionImplementor.java:60) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.afterTransaction(LogicalConnectionManagedImpl.java:167) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.afterTransaction(JdbcCoordinatorImpl.java:276) at org.hibernate.internal.SessionImpl.afterOperation(SessionImpl.java:550) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1464) at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1665) at com.art.vesal.backend.core.dao.impl.UserDaoImpl.get(UserDaoImpl.java:238) at com.art.vesal.backend.core.controller.customer_management.UserControllerImpl.get(UserControllerImpl.java:159) at com.art.vesal.backend.core.controller.customer_management.CustomerControllerImpl.checkCustomer(CustomerControllerImpl.java:598) at com.art.vesal.backend.core.controller.messaging.MTSMSControllerImpl.sendMessageManyToMany(MTSMSControllerImpl.java:282) at com.art.vesal.backend.core.controller.messaging.ArtMTSMSImpl.sendMessageManyToMany(ArtMTSMSImpl.java:140) at com.art.vesal.backend.core.controller.rest.MessageRelayRest.sendMessageManyToMany(MessageRelayRest.java:26) at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52) at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124) at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167) at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219) at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79) at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:475) at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:397) at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81) at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at org.glassfish.jersey.internal.Errors.process(Errors.java:292) at org.glassfish.jersey.internal.Errors.process(Errors.java:274) at org.glassfish.jersey.internal.Errors.process(Errors.java:244) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234) at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680) at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:356) at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:190) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515) at java.base/java.lang.Thread.run(Thread.java:833)
Where is the problem and how do I fix it such hibernate connection polling and so on?

ijxebb2r

ijxebb2r1#

我不知道@Service注解是做什么的,但我猜它定义了一个单例,因此您在所有并发线程之间共享一个Session
当然,这是违法的。

相关问题