【问题标题】:Async service with session带会话的异步服务
【发布时间】:2015-01-19 21:05:08
【问题描述】:

我有一个要调用存储函数的方法。我希望它异步完成它的工作。这就是我所拥有的,但似乎 .doWork() 从未启动,因为当我调用 getDao.deleteAll() 时,存储的函数没有运行。

@Transactional
    public void delete()
    {

        final Session session = (Session) entityManager.getDelegate();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(new Runnable()
        {
            @Override
            public void run()
            {
                LOGGER.warn("starting");
                session.doWork(new Work()
                {
                    @Override
                    public void execute(Connection connection) throws SQLException
                    {
                        try
                        {

                            CallableStatement purgeArchived = connection.prepareCall("{call deleteAll()}");
                            purgeArchived.execute();
                        }
                        catch (SQLException exception)
                        {
                            LOGGER.warn("Failed to purge archive points. Reason: " + exception);
                        }
                    }
                });
                LOGGER.warn("stopping");
            }
        });
        executorService.shutdown();
    }

我看到记录器已经记录了"starting",但它从未到达"stopping",为什么会发生这种情况?

【问题讨论】:

  • 尝试在run方法中移动final Session session = (Session) entityManager.getDelegate();
  • 刚刚试过,没成功
  • executorService.shutdown(); 之后尝试使用while (!executorService.isTerminated()) { }。这将使当前线程等待,直到ExecutorService 中的线程完成。这是出于测试目的,因为如果它在这里结束,则意味着问题出在初始化该线程的主线程中。
  • 问题出在:CallableStatement purgeArchived = connection.prepareCall("{call deleteAll()}");我把记录语句放在后面,prepareCall 被记录后什么都没有。不知道为什么..
  • 似乎连接正在关闭,而另一个线程仍在工作。这是您在管理线程和外部线程管理连接的打开和关闭时遇到的问题。

标签: java hibernate jdbc


【解决方案1】:

请注意,当您有单独的线程时,@Transaction 没有实际意义,因为事务通常是线程绑定的。

您需要在 run() 中从工厂获取一个新的 entityManager

也可以选择@Async,它更干净。

再次注意@Async的事务性

@Async and @Transactional: not working

作为一般经验法则,如果您想让某些工作异步 - 将其视为单个工作单元和单独的事务。

【讨论】:

  • 所以目前我的 DAO 正在扩展一个 GenericDAOJpa,它在那里创建实体管理器。所以你是说我应该在 run() 中创建一个新的? @bhantol
  • 添加一个新的 entityManager 确实有效!但你能告诉我背后的原因吗?谢谢@bhantol
  • 您还建议使用@Async 而不是@Transactional?还是两者都用?
  • @JennyC EntityManagers 不是线程安全的。 docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/… 在 run() 中添加获取 EntityManager 的原因是它能够在该线程中获得一个新的 entityManager,而不是使用在父/另一个线程中创建的 entityManager。
  • 是的,用相同的方法注释 @Async@Transnational。 (事务被隔离)
猜你喜欢
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2022-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多