gpt4 book ai didi

java - 在 AsyncUncaughtExceptionHandler 中获取 Hibernate Session

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:00:53 25 4
gpt4 key购买 nike

@Async 操作因异常而失败时,我想在数据库中创建一个异常日志。

您可以在下面看到 AsyncExecutorConfigurationAsyncExceptionHandler 类的实现。

AsyncExceptionHandler 类中,当我调用试图访问数据库的服务时,我得到:org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread

@Configuration
@EnableAsync
public class AsyncExecutorConfiguration implements AsyncConfigurer {

@Autowired
private AsyncExceptionHandler asyncExceptionHandler;

private static final int CORE_POOL_SIZE = 3;
private static final int MAX_POOL_SIZE = 3;
private static final int QUEUE_CAPACITY = 24;
private static final String THREAD_NAME_PREFIX = "AsynchThread-";

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return asyncExceptionHandler;
}

}

@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Autowired
private NotificationService notificationService;

@Override
@Transactional(rollbackFor = Exception.class, readOnly = false)
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
AsyncErrorLog log = new AsyncErrorLog(ex);
notificationService.saveLogAndNotify(log); // throws exception "Could not obtain transaction-synchronized Session for current thread"
}
}


@Service
public class MyServiceImpl implements MyService {

@Override
@Async
@Transactional(rollbackFor = Exception.class, readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void doSomething(Long id) {
// I can execute database operations here

}
...

@Async 函数本身已经有一个有效的 session 。我应该怎么做才能在 AsyncExceptionHandler 类中也有一个有效的 session ?

--

更新

这里是我们得到错误的 NotificationServiceImplLogDaoImpl.class 的简化实现。

@Service
public class NotificationServiceImpl implements NotificationService {

@Autowired
private LogDao logDao;

@Override
@Transactional(rollbackFor = Exception.class, readOnly = false)
public void saveLogAndNotify(Log log) {
return logDao.createLog(log);
}


@Repository
public class LogDaoImpl{

@Autowired
protected SessionFactory sessionFactory;


@Override
public void createLog(Log log) {
sessionFactory.getCurrentSession().saveOrUpdate(log);
}

最佳答案

根据 Hibernate 异常;如果您不使用 Spring Data,则必须确保通知服务在 Hibernate session 中显式调用数据库。

另一方面,根据我的经验,UncaughtExceptionHandler 的主要用例(通常)用于:

  1. 一个简单的最后手段来处理程序员可能不知道的 RuntimeException,由于某种原因不能(或没有)在代码中捕获
  2. 一种在程序员无法控制的代码中捕获异常的方法(例如,如果您直接在某些第三方库上调用 Async,等等)

两者的共同点是这个Handler是用来做一些意想不到的事情的。事实上,Spring 本身会解释您自己的代码和 Spring Async 中的“意外情况”已经 sets a default one for you that will log to the console (代码 here ),让您不必担心流氓异常杀死线程并且不知道为什么。 (注意:源代码中的消息说它捕获了一个“意外”异常。当然异常是意外的,但这些是你真的不知道会发生的。Spring Async 将记录它给你。)

既然如此,在您的示例中,由于您正在执行 Spring 数据库操作并且应该确切地知道 #doSomething 内部发生了什么,所以我会删除 AUEH a try-catch(和/或-finally)并处理#doSomething 中的异常:

@Service
public class MyServiceImpl implements MyService {

// Self autowired class to take advantage of proxied methods in the same class
// See https://stackoverflow.com/questions/51922604/transactional-and-stream-in-spring/51923214#51923214
private MyService myService;

private NotificationService notificationService;

@Override
@Async
public void doSomething(Long id) {
// I can execute database operations here
try {
myService.doDatabaseOperations(...);
} catch(DatabaseAccessException e) {
AsyncErrorLog log = new AsyncErrorLog(ex);
notificationService.saveLogAndNotify(log);
}
// Other exceptions (from DB operations or the notifications service) can be
// handled with other "catches" or to let the SimpleAsyncExHandler log them for you.
// You can also use standard multithreading exception handling for this
}

@Transactional(rollbackFor = Exception.class, readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void doDatabaseOperations(...) {
...
}

}

关于java - 在 AsyncUncaughtExceptionHandler 中获取 Hibernate Session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53785627/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com