在线程中删除时的TransactionRequiredException [英] TransactionRequiredException when deleting in threads

查看:131
本文介绍了在线程中删除时的TransactionRequiredException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试通过Hibernate使用多个线程从数据库中删除数据时遇到问题.

I'm having a problem when I trying to delete data from the DB using multiple threads with Hibernate.

回购:

@Modifying
@Query("DELETE FROM Customer cus  WHERE cus.customerId in :customerIds")
public void deleteByCustomerIds(@Param("customerIds") List<Long> customerIds);

服务:

public runDelete (List<Long> customerIds) {
    List<List<Long>> partitions = Lists.partition(customerIds, 5000);

    for(int i = 0; i < partitions.size(); i++ ) {
        final int index = i;
        Runnable thread = () -> deleteCustomersInBatches(partitions.get(index));
        new Thread(thread).start();
    }
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
private void deleteCustomerInBatches(List<Long> customerIds) {

    for (List<Long> batch : Lists.partition(oldCalcIds, 1000)) {
        customerRepo.deleteByCustomerIds(batch);
    }
}

这是代码的样子,我在进行回购调用的服务层上有@Transactional标记.

This is how code looks like, I have the @Transactional tag on the service layer where the repo call is being made.

at java.lang.Thread.run(Thread.java:748)由以下原因引起: javax.persistence.TransactionRequiredException:执行 更新/删除查询 在org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:54)

at java.lang.Thread.run(Thread.java:748) Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:54)

我不断收到此错误.任何帮助表示赞赏.

I keep getting this error. Any help is appreciated.

推荐答案

这是因为您要从同一个bean中调用@Transactional方法.

It's because you're invoking @Transactional method from within same bean.

@Transactional仅适用于由spring创建的代理所调用的方法.这意味着,当您创建@Service或其他bean时,从外部调用的方法将是事务性的.如果从Bean中调用,则不会发生任何事情,因为它不会通过代理对象传递.

@Transactional only works on methods invoked on proxies created by spring. It means, that when you create a @Service or other bean, method called from the outside will be transactional. If invoked from within bean, nothing will happen, as it doesn't pass through proxy object.

最简单的解决方案是将方法移至另一个bean.如果您真的想将其保留在同一组件中,则需要调用它,以便在Spring AOP中将其包装在代理中.您可以这样操作:

The easiest solution would be to move the method to another bean. If you really want to keep it within same component, then you need to invoke it, so that it gets wrapped in proxy by spring AOP. You can do this like that:

private YourClass self;

@Autowired
private ApplicationContext applicationContext;

@PostConstruct
public void postContruct(){
    self = applicationContext.getBean(YourClass.class);
}

然后在self上调用方法将导致打开交易.

Then invoking method on self would result in opening a transaction.

这篇关于在线程中删除时的TransactionRequiredException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆