java - 如何将 Spring 事务管理与 Hibernate 集成?
问题描述
我一直在尝试使用 HibernateTransactionManager 来管理我的服务层中的事务,但它不起作用。用于创建 PlatformTransactionManager 的 Java 类配置:
@Configuration
@EnableTransactionManagement
@PropertySource("classpath:hibernateConfig.properties")
public class HibernateConfig {
@Value("${hibernate.dialect}")
private String dialect;
//Other hibernate properties
@Autowired
private DataSource dataSource;
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", dialect);
//Other hibernate properties removed here for brevity
return hibernateProperties;
}
@Bean
@DependsOn("dataSource")
public SessionFactory sessionFactory() throws IOException {
LocalSessionFactoryBean sessionFactoryBean =
new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setPackagesToScan("com.ldp.vigilantBean.domain");
sessionFactoryBean.setHibernateProperties(hibernateProperties());
sessionFactoryBean.afterPropertiesSet();
return sessionFactoryBean.getObject();
}
@Bean
@DependsOn("sessionFactory")
public PlatformTransactionManager platformTransactionManager() throws IOException {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory());
txManager.afterPropertiesSet();
return txManager;
}
}
在这个方法调用的后面,有两次对持久层的调用,最后抛出了一个运行时异常。所以我希望回滚这两个对存储库的调用。
@Override
@Transactional(rollbackFor = { RuntimeException.class })
public boolean removeCartItem(Long cartItemId) {
Cart cart = getCartOutOfContext();
Optional<CartItem> optCartItemToRemove =
cart.getCartItems()
.stream()
.filter(cartItem -> cartItem.getCartItemId().equals(cartItemId))
.findAny();
if (optCartItemToRemove.isPresent()) {
CartItem cartItemToRemove = optCartItemToRemove.get();
//There is a bug with PersistentSet in Hibernate that makes
//using .contains() and .remove() methods of Set interface unpredictable.
//This is a workaround: reset the whole set.
cart.setCartItems(
cart.getCartItems().stream()
.filter(cartItem -> !cartItem.equals(cartItemToRemove))
.collect(Collectors.toSet())
);
Optional<Product> optProduct =
productRetrievalRepository.getProductById(cartItemToRemove.getProduct().getProductId());
if (!optProduct.isPresent())
throw new IllegalArgumentException("Specified product not found");
Product productToRemove = optProduct.get();
productToRemove.setUnitsInOrder(productToRemove.getUnitsInOrder() - cartItemToRemove.getQuantity());
//First call
productAlterRepository.updateProduct(productToRemove);
//Second call
cartRepository.updateCart(cart);
if (true) throw new RuntimeException("An exception to check transactions");
return true;
} else
return false;
}
用于管理产品的存储库:
@Repository
class ProductAlterRepositoryImpl implements ProductAlterRepository {
private SessionFactory sessionFactory;
public ProductAlterRepositoryImpl(
@Autowired
SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public Optional<Product> updateProduct(Product product) {
try (Session session = sessionFactory.openSession()) {
session.getTransaction().begin();
session.merge(product);
session.getTransaction().commit();
}
return Optional.of(product);
}
}
我不明白为什么在我的服务方法中抛出 RuntimException 之前所做的更改没有回滚:我使用相同的会话工厂来初始化平台事务管理器并通过我的存储库中的 Session 进行更改。另外,我的记录器中有这条线
*** LOG4J *** HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
如果我是对的,当只使用一个资源(在我的例子中是 Hibernate 存储库)时,您不需要像 Atomikos 这样的全局事务提供程序。我认为假设有 3 个事务:一个外部(服务调用)和 2 个内部(存储库)。这个想法是,如果内部事务之一失败,它应该导致外部事务回滚,这意味着对存储库的所有两个调用都将被回滚。
解决方案
在 updateProduct(Product) 内部,除了服务级别的声明之外,您还再次打开了程序化事务。因此它将忽略 Spring 容器管理的事务管理器,并将单独使用它自己的。能否请您删除并重试。
推荐阅读
- c# - 如何观察不同类别的整数
- php - 使用 .htaccess 在 localhost 上重定向 Wordpress 页面时,Page slug 无休止地重复
- file - 将 https 重定向到 http(下载文件)
- r - R - 从文本文档中提取字符串
- python - tk_app.mainloop() 导致 mac 崩溃并重新启动
- go - 尝试了 monad 模式,但仍然有重复的错误处理
- php - 访问模型中关系方法内的字段
- java - 从 Quartz 调度程序调用函数时,如何将 HttpRequest/Reponse 作为参数传递给函数?
- javascript - 使用 .then() 从 Promise 转换为 async/await
- object-detection - 如何计算掩码 rcnn 中的 TN(真阴性)?