当前位置: 首页 > 知识库问答 >
问题:

Spring中当前线程中禁止@transactional

司徒池暝
2023-03-14

我在寻找下一个问题的解决方法。我使用Spring,我有一些不应该被阻塞的Executor的线程(至少读/写数据库)。有几个任务可以通过这个执行器执行,我不知道哪一个可以使用@transactional方法或任何其他方法来访问数据库。我想禁止在执行者的线程中打开新的事务,怎么做?

小例子

@Component
public class Service {

    public void execute() {
        System.out.println("I don't need transaction to execute");
    }
}

@Component
public class Service2 {

    @Transactional
    public void execute() {
        System.out.println("I've opened new transaction!");
    }
}

@Component
public class NonTransactionalExecutor {

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private Service service;

    @@Autowired
    private Service2 service2;

    public void doInExecutor() {
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                // Is there anything I could do to get exception on service2.execute?
                service.execute();
                service2.execute();
            }
        });
    }
}
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:140)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:109)
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:67)
    at org.postgresql.core.PGStream.receiveChar(PGStream.java:293)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1936)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306)
    - locked <4cd92d89> (a org.postgresql.core.v3.QueryExecutorImpl)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:307)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:293)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:270)
    at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:224)
    at com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:286)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:510)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:464)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishResourceOnCheckout(C3P0PooledConnectionPool.java:339)
    - locked <73ed3d84> (a java.lang.Object)
    at com.mchange.v2.resourcepool.BasicResourcePool.attemptRefurbishResourceOnCheckout(BasicResourcePool.java:1733)
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:558)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:758)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:685)
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139)
    at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380)
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228)
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171)
    at org.hibernate.internal.SessionImpl.connection(SessionImpl.java:450)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:450)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)

共有1个答案

姬银龙
2023-03-14

您可能会使用装饰器模式。实现您自己的PlatformTransactionManager并将您当前的管理器作为委托传递给它。在gettransaction中,如果当前线程不是您所期望的,则抛出异常。

public class MyTransactionManager implements PlatformTransactionManager {
    private final PlatformTransactionManager delegate;

    public MyTransactionManager(PlatformTransactionManager delegate) {
        this.delegate = delegate;
    }

    @Override
    public void commit(TransactionStatus status) {
        delegate.commit(status);
    }

    @Override
    public TransactionStatus getTransaction(TransactionDefinition definition) {
        if (Thread.getCurrentThread() == /*something*/) {
            return delegate.getTransaction(definition);
        }
        else {
            throw new RuntimeException();
        }
    }

    @Override
    public void rollback(TransactionStatus status) {
        delegate.rollback(status);
    }
}
 类似资料:
  • 本文向大家介绍emacs 中止当前命令,包括了emacs 中止当前命令的使用技巧和注意事项,需要的朋友参考一下 示例 通常,您会进入一种状态,其中正在进行部分键入的命令序列,但是您想中止它。您可以使用以下任一键绑定中止它: C-g EscEscEsc

  • 问题内容: 之前已针对Android,ObjectiveC和C++解决了此问题,但显然不适用于Python。如何可靠地确定当前线程是否为主线程?我可以想到一些方法,但没有一种方法能让我真正满意,因为考虑到与存在的方法相比,它可能是如此简单。 主线程是这样实例化的: 所以一个人可以做 但是这个名字是固定的吗?我见过的其他代码检查了线程名称中是否包含任何代码。 存储启动线程 我可以在程序启动时即在没有

  • 所以一个人可以做 但这个名字固定了吗?我看到的其他代码检查了是否包含在线程名称的任何地方。 我可以在程序启动时存储对起始线程的引用,也就是在没有其他线程的时候。这是绝对可靠的,但对于这样一个简单的查询来说太麻烦了? 有没有更简洁的方法?

  • 我阅读了很多关于这个问题的线程和解决方案(包括这个SO解决方案),但在发送预飞行请求时仍然有403错误。 我使用的是Spring Data Rest,只要没有发送选项,我就可以很好地处理我的存储库。我还没有使用Spring Security,但我计划很快配置它。以下是我当前的配置:

  • 问题内容: 我正在关注youtube上的教程,但是OpenGL存在我无法解决的问题。我不知道该如何解决。 主要 问题答案: 您需要调用glfwMakeContextCurrent将OpenGL上下文绑定到您的线程。LWJGL网站上也有一个工作示例。

  • 问题内容: 我有一个使用spring和hibernate的java stuts2 Web应用程序。 我越来越。 SpringBean.xml hibernate.cfg.xml CustomerServiceImpl.java CustomerDaoImpl.java CustomerAction.java 我得到的例外 问题答案: 您在Spring配置中指定了一个事务管理器,但是没有关于何时或何