简体   繁体   English

Hibernate SessionFactory,无法获取当前线程的事务同步会话

[英]Hibernate SessionFactory and could not obtain transaction-synchronized session for current thread

I know this question has been asked before however none of the solutions have worked for me. 我知道在问过这个问题之前,没有一个解决方案对我有用。

I am trying to hit a controller to populate an index. 我试图打一个控制器来填充索引。 The issue arises when I try and search the database for updates. 当我尝试在数据库中搜索更新时会出现问题。

Here is are the classes I am dealing with: 这是我要处理的类:

Configuration: 组态:

@Configuration
@EnableTransactionManagement
public class WebApplication implements WebApplicationContextInitializer, ApplicationContextAware {

    @Bean(name="dataSource")
    public DataSource getDataSource() throws IOException {
        InitialContext initialContext = new Context();
        return (DataSource) initialContext.lookup("java:comp/env/jdbc/myDataSource");
    }

    @Bean(name="sessionFactory")
    public SessionFactory getSessionFactory() throws IOException {
        LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(getDataSource());
            sessionBuilder.scanPackages(PropertyUtil.getInstance().getPropertySplitTrimmed("hibernate", "packagesToScan"));
            sessionBuilder.addProperties(PropertyUtil.getInstance().getProperties("hibernate"));
            return sessionBuilder.buildSessionFactory();
    }

    @Bean(name="transactionManager")
    public HibernateTransactionManager transactionManager() throws IOException {
        return new HibernateTransactionManager(getSessionFactory());
    }
}

Controller: 控制器:

@RestController
@Transactional
@RequestMapping("/persons")
public class IndexController {
   @Autowired
   PersonsDao personsDoa;

   private ExecutorService executorService = Executors.newFixedThreadPool(100);

  @RequestMapping(value="/index")
  public void populateIndex(@DefaultValue("") @RequestParam String name){
    ...
    ...
    List<Future<Persons>> holder = new ArrayList<>();

    for(Persons p : people){
       String name = p.name();
       Future<Person> f = this.executorService.submit(new Callable<Person>(){
          @Override
          public Person call() throws Exception {
            return personsDao.findByName(name);  // <-- Throws error here
          }
       });
       holder.add(f);  // process the array later once all threads are finished
    }
    ...
    ...
  }
}

UPDATE: I've updated my Controller according to some suggestions, however I am still receiving the same error 更新:我已经根据一些建议更新了控制器,但是我仍然收到相同的错误

Controller: 控制器:

@RestController
@Transactional
@RequestMapping("/persons")
public class IndexController {
   @Autowired
   PersonsDao personsDoa;

   private ExecutorService executorService = Executors.newFixedThreadPool(100);

  @RequestMapping(value="/index")
  public void populateIndex(@DefaultValue("") @RequestParam String name){
    ...
    ...
    List<Future<Persons>> holder = new ArrayList<>();
    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(sessionFactory.getCurrentSession()));  //<-- THROWS ERROR HERE
    for(Persons p : people){
       String name = p.name();
       Future<Person> f = this.executorService.submit(new Callable<Person>(){
          SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResources(sessionFactory);
          Session session = holder.getSession();
          @Override
          public Person call() throws Exception {
            Transaction t = session.getTransaction();
            t.begin();
            Persons p = personsDao.findByName(name);
            t.commit();
            session.flush();
            return p;
          }
       });
       holder.add(f);  // process the array later once all threads are finished
    }
    ...
    ...
  }
}

Usualy the request thread use only one shared Session, this session is binded at the start of the request, and unbinded at the end of the request, but given you want to use it in another thread, we must : 通常,请求线程仅使用一个共享会话,此会话在请求开始时绑定,在请求结束时取消绑定,但是鉴于您要在另一个线程中使用它,我们必须:

1_ prevent the session from being closed from the Request Thread. 1_防止从请求线程关闭会话。

2_ bind this session to the new thread, to offer the TransactionManager to works with same Session. 2_将此会话绑定到新线程,以提供TransactionManager与同一会话一起使用。

First the current Session must not be closed, so if you are using the OpenInViewFilter, you need to add a method before calling the new Thread. 首先,当前会话不得关闭,因此,如果您使用的是OpenInViewFilter,则需要在调用新线程之前添加一个方法。

OpenEntityManagerInViewFilter.getCurrent().keepEmfOpen(request);            

Then inside the Thread you need to attach the current session. 然后,在线程内部,您需要附加当前会话。

public void attachThread() {// this must bind the session to this thread.
    OpenEntityManagerInViewFilter.getCurrent().registerEmfs(request, session);
}

private boolean registerEmf(String key, ServletRequest request, EntityManagerFactory emf){
        if (emf == null)
            return true;
        if (TransactionSynchronizationManager.hasResource(emf))         
            return true;        
        else {
            boolean isFirstRequest = true;
            WebAsyncManager asyncManager = null;
            if (request!=null){
                asyncManager = WebAsyncUtils.getAsyncManager(request);
                isFirstRequest = !(request instanceof HttpServletRequest) || !isAsyncDispatch((HttpServletRequest) request);
            }
            if (emf.isOpen())
            if (isFirstRequest || !applyEntityManagerBindingInterceptor(asyncManager, key)) {
                logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewFilter");
                try {
                    EntityManager em = createEntityManager( emf );
                    EntityManagerHolder emHolder = new EntityManagerHolder( em );
                    TransactionSynchronizationManager.bindResource( emf, emHolder );
                    if (asyncManager!=null)
                        asyncManager.registerCallableInterceptor( key, new EntityManagerBindingCallableInterceptor( emf, emHolder ) );
                    return false;
                }
                catch (PersistenceException ex) {
                    throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
                }
            }
        }
        return true;
    }

in case of OpenSessionInViewFilter : 如果是OpenSessionInViewFilter:

private void openHibernateSessionInView(){
  Session session=SessionFactoryUtils.getSession(sessionFactory,true);
  SessionHolder holder=new SessionHolder(session);
  if (!TransactionSynchronizationManager.hasResource(sessionFactory)) {
    TransactionSynchronizationManager.bindResource(sessionFactory,holder);
  }
}

private void closeHibernateSessionInView(){
  if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
    SessionHolder sessionHolder=(SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
    if (sessionHolder.getTransaction() != null && !sessionHolder.getTransaction().wasRolledBack() && !sessionHolder.getTransaction().wasCommitted()) {
      sessionHolder.getTransaction().commit();
    }
    SessionFactoryUtils.closeSession(sessionHolder.getSession());
  }
}

暂无
暂无

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

相关问题 Spring和Hibernate-无法获得当前线程的事务同步会话 - Spring and Hibernate - Could not obtain transaction-synchronized Session for current thread Hibernate无法获取当前线程的事务同步会话 - Hibernate Could not obtain transaction-synchronized Session for current thread 休眠5-无法获取当前线程的事务同步会话; - hibernate 5 - Could not obtain transaction-synchronized Session for current thread; 休眠-无法获取当前线程的事务同步会话 - Hibernate - Could not obtain transaction-synchronized Session for current thread 无法检索预绑定的Hibernate会话 - 无法获取当前线程的事务同步会话 - Could not retrieve pre-bound Hibernate session - Could not obtain transaction-synchronized Session for current thread 迁移到Hibernate 4 + Spring 4.2.2:org.hibernate.HibernateException:无法获取当前线程的事务同步Session - migration to hibernate 4 + spring 4.2.2: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread HibernateException:无法获取当前线程的事务同步会话 - HibernateException: Could not obtain transaction-synchronized Session for current thread 无法获取当前线程的事务同步会话 - Could not obtain transaction-synchronized Session for current thread Spring 4.3.0.RELEASE + Hibernate 5.2.0.Final-无法获得当前线程的事务同步会话 - Spring 4.3.0.RELEASE + Hibernate 5.2.0.Final - Could not obtain transaction-synchronized Session for current thread org.hibernate.HibernateException:无法获取当前线程的事务同步会话 - org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM