Java 如何将Spring事务管理与Hibernate集成?
我一直在尝试使用HibernateTransactionManager来管理服务层中的事务,但它不起作用。 用于创建PlatformTransactionManager的Java类配置:Java 如何将Spring事务管理与Hibernate集成?,java,spring,hibernate,spring-transactions,Java,Spring,Hibernate,Spring Transactions,我一直在尝试使用HibernateTransactionManager来管理服务层中的事务,但它不起作用。 用于创建PlatformTransactionManager的Java类配置: @Configuration @EnableTransactionManagement @PropertySource("classpath:hibernateConfig.properties") public class HibernateConfig { @Value(&qu
@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;
}
如果我是对的,当只使用一个资源(在我的例子中是Hibernate存储库)时,您不需要像Atomikos这样的全局事务提供程序。
我认为应该有3个事务:一个外部事务(服务调用)和两个内部事务(到存储库)。其思想是,如果其中一个内部事务失败,它将导致外部事务回滚,这意味着对存储库的所有两个调用都将回滚。在updateProduct(产品)内部,除了服务级别的声明性事务外,您还再次打开了编程事务。因此,它将忽略Spring容器管理的事务管理器,并单独使用自己的事务管理器。
@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;
}
请删除该选项,然后重试。无效。我认为应该有3个事务:一个外部事务(服务调用)和两个内部事务(到存储库)。其思想是,如果其中一个内部事务失败,它将导致外部事务回滚,这意味着对存储库的所有两个调用都将回滚。@服务实现中的事务性就足够了,建议这样做。请删除所有编程事务管理内容(开始/提交/回滚)。在repository/dao级别,只保留与DB处理相关的代码。一旦您的行会话.getTransaction().commit();被执行了,它不能倒转好了,它成功了。我不知道为什么我不认为语法管理的事务在这里是一个障碍。非常感谢您的时间和努力。
*** LOG4J *** HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]