Java 如何获取Spring事务内部的连接?

Java 如何获取Spring事务内部的连接?,java,spring,jdbc,connection,spring-transactions,Java,Spring,Jdbc,Connection,Spring Transactions,想象一下这个代码: foo() { Connection conn = ...; } foo()已从具有注释@Transactional的方法调用。如何获取当前的JDBC连接?请注意,foo()在bean中(因此它可以有@Autowired字段),但是foo()不能有参数(因此我不能从某个地方传递连接) [EDIT]我正在使用jOOQ,它需要数据源或连接。我的问题:我不知道配置了哪个事务管理器。它可以是任何东西;JavaEE,基于数据源,通过JNDI获取数据源。我的代码不是一个应用程

想象一下这个代码:

foo() {
     Connection conn = ...;
}
foo()
已从具有注释
@Transactional
的方法调用。如何获取当前的JDBC连接?请注意,
foo()
在bean中(因此它可以有
@Autowired
字段),但是
foo()
不能有参数(因此我不能从某个地方传递连接)

[EDIT]我正在使用jOOQ,它需要数据源或连接。我的问题:我不知道配置了哪个事务管理器。它可以是任何东西;JavaEE,基于数据源,通过JNDI获取数据源。我的代码不是一个应用程序,而是一个库。我需要吞下别人放在我盘子里的东西。同样,我不能请求Hibernate会话工厂,因为使用我的应用程序可能不使用Hibernate

但是我知道其他代码,比如Spring Hibernate集成,可以通过某种方式从事务管理器获取当前连接。我的意思是,Hibernate不支持Spring的事务管理器,因此粘合代码必须使SpringAPI适应Hibernate的期望。我需要做同样的事情,但我不知道它是如何工作的


[EDIT2]我知道有一个活动事务(即Spring在某处有一个连接实例,或者至少有一个可以创建一个的事务管理器),但我的方法不是@Transactional。我需要调用以
java.sql.Connection
为参数的构造函数。我应该怎么做?

如果您在JDBC中使用Spring事务,请配置
JdbcTemplate
,并使用
JdbcTemplate.execute(ConnectionCallback)
访问当前事务。这是访问Spring配置的连接的标准方法。

我假设您使用的是普通Jdbc,您需要做的是:

BaseDao {
    @Autowired
    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Connection getConnection() {
        // ....use dataSource to create connection
        return DataSourceUtils.getConnection(dataSource);
    }
}

FooDao extends BaseDao {
    // your foo() method
    void foo() {
       Connection conn = getConnection();
       //....
    }
}

您可能可以尝试使用
DataSourceUtils.getConnection(dataSource)
,它应该返回数据源的当前连接

更新: 根据您的评论和org.springframework.transaction.support.TransactionSynchronizationManager的源代码:

正如我所说,获取连接的关键是数据源名称,如果无法获取,查看源代码的一种方法是尝试以下方法:

TransactionSynchronizationManager.getResourceMap()
将返回数据源到当前线程中ConnectionHolder的映射,假设事务中只涉及1个资源,您可能可以执行
map.values().get(0)
以获取第一个ConnectionHolder,通过调用
.getConnection()

因此,本质上称之为:

TransactionSynchronizationManager.getResourceMap().values().get(0.getConnection()

不过,可能必须有更好的方法:-)

(完全根据评论线程重写;不确定我最初的答案为什么集中在Hibernate上,而不是我现在正在使用的)

事务管理器与数据源完全正交。有些事务管理器直接与数据源交互,有些通过中间层(例如Hibernate)交互,有些通过容器提供的服务(例如JTA)交互

当您将一个方法标记为
@Transactional
时,这意味着Spring将在加载您的bean时生成一个代理,该代理将被交给希望使用您的bean的任何其他类。当调用代理的方法时,它(代理)要求事务管理器为其提供一个未完成的事务或创建一个新的事务。然后它调用实际的bean方法。当bean方法返回时,代理再次与事务管理器交互,要么说“我可以提交”,要么说“我必须回滚”。这个过程有曲折;例如,一个事务性方法可以调用另一个事务性方法并共享同一个事务


当事务管理器与
数据源
交互时,它并不拥有
数据源
。您不能要求事务管理器为您提供连接。相反,必须插入一个特定于帧的对象,该对象将返回连接(例如Hibernate
SessionFactory
)。或者,您可以使用静态事务感知实用程序类,但这些类又与特定的框架相关联。

所有这些都有点令人恼火的是,Spring文档主要是用营销语言编写的,隐藏了幕后的丑陋

简而言之:

您的数据源存储在线程本地上下文中,这是基于请求总是由唯一线程处理的假设(基本上是有效的)

因此,Spring以一种非常复杂的方式将您的内容本地存储到当前的执行线程中,这是一件微不足道的事情,但在Spring文档中没有足够清晰地重复。Spring基本上将您的东西放在“全局上下文”中,以避免通过所有接口和方法定义来实现它。一开始看起来有点神奇,但实际上只是化妆而已

因此,您最终将使用静态DataSourceUtils方法调用来检索您的资料。

3其他方法:

@组件
公共类MyServicentransactional{
@自动连线
私有事务模板TransactionTemplate;
@自动连线
私有数据源;
公共空间{
transactionTemplate.executeWithoutResult(状态->{
Connection Connection=DataSourceUtils.getConnection(dataSource);
//我们走吧。。。
});
}
}
@服务
公共类MyServiceTransaction{
@自动连线
私有数据源;
@交易的
公共空间{
Connection Connection=DataSourceUtils.getConnection(dataSource);