【问题标题】:How can I use @Transactional in multithreaded environment如何在多线程环境中使用 @Transactional
【发布时间】:2019-12-04 11:11:18
【问题描述】:

我正在使用多线程进行插入操作。我用注解我的方法是@Transaction注解。但我无法执行低于异常的插入操作。

线程“Thread-21”javax.persistence.TransactionRequiredException 中的异常:执行更新/删除查询 在 org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

【问题讨论】:

  • 显示该方法及其调用。

标签: spring jpa spring-data-jpa spring-transactions


【解决方案1】:

因为没有代码......为了让它工作,你必须

  1. 用@Transactional 注释你的删除方法——我们称之为delete
  2. 必须从 bean 外部调用该方法才能启动 AOP

所以像

这样的内部调用
void doSomething(){
    this.delete();
}

不会工作

但是

@Autowired
YourBean bean;

...
bean.delete(); 

会做好的

【讨论】:

    【解决方案2】:

    因为 spring bean 被包装了,所以你必须从 Thread 调用被包装的方法:

    @Autowire
    private final MyService ms=null;
    
    public void removeMultithreaded(int[] userIds){
      for(int i =0; i< userIds.length; i++) {
        int userId=userIds[i];
        new Thread(()-> ms.delete(userId)).start();
      }
    }
    

    在此代码中,您调用 delete 必须用 @Transactional 注释的内容。

    警告:您可以同时删除的 userId 数量受连接池大小的限制!由于删除操作可能比从连接池中收集和释放更快,因此您可能永远不会遇到麻烦,即使您必须删除的用户数量超过连接池允许的数量。

    【讨论】:

    • 教(可能是年轻人)在需要时自己运行线程而不是使用工作池的坏习惯是非常糟糕的。
    • 工作池与连接池可能会产生死锁。但有趣的是,什么答案被赞成。 :)
    • 从这个角度来看,单独的线程和工作池是一回事。工作池是关于重用成本高昂的线程。如果您说它容易陷入僵局,那么您的答案也是如此
    • @Antoniossss 独立线程的数量不受限制,死锁的可能性很小。一个完整的工作池如果不接受针对连接池的更多工作,肯定会产生死锁。
    • 硬件限制了它。所以那是一样的。你可以使用缓存池执行器,它可以疯狂地创建最大可能的线程数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    相关资源
    最近更新 更多