spring 中的多个事务管理器,并在运行时选择一个

Posted

技术标签:

【中文标题】spring 中的多个事务管理器,并在运行时选择一个【英文标题】:Multiple transaction managers in spring and select one at runtime 【发布时间】:2016-09-04 03:19:55 【问题描述】:

对于每个客户,我都有单独的数据库,但每个客户的业务逻辑和表都是相同的。我想要每个客户端的通用服务和 dao 层。在 dao 中,我根据登录的用户客户端选择数据源。在@Transactional 中,我必须传递事务管理器的 bean id。如何制作带有@Transactional注解的公共服务层。

这里有同样的问题

    Multiple transaction managers - Selecting a one at runtime - Spring

    Choose between muliple transaction managers at runtime

但没人回复

【问题讨论】:

在不同的注释上,不同的数据库但相同的表是什么意思?你的意思是每个数据库都有相同的架构? 是的..每个数据库都有相同的架构 不回答问题,实际上是在为您寻找解决方案,但除此之外,当架构相同时,我认为为每个客户端设置单独的数据库并不是一个好主意,为什么不使用一个单一的数据库?即使你有 100 个客户端会发生什么,这会导致 100 个数据库,这意味着要管理 100 个数据库连接。那是资源占用。 这是客户要求。他们说,出于安全原因,他们的数据库应该与其他客户端不同。他们将来可以管理他们的数据库。客户不会超过 5 个。 您不需要多个数据源/事务管理器。好吧,您需要DataSources,但其他一切都可以是单例。我们在 10 多年前就这样做了。解决方案记录在here。根据您的需要,AbstractRoutingDataSource 可能就是您所需要的,并且没有多个事务管理器之类的东西。 【参考方案1】:

您无需在多个事务管理器之间进行配置和切换即可实现最终目标。而是使用 Spring 提供的org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource 机制。

详细的例子可以在这里找到:

    https://spring.io/blog/2007/01/23/dynamic-datasource-routing/ http://howtodoinjava.com/spring/spring-orm/spring-3-2-5-abstractroutingdatasource-example/

【讨论】:

【参考方案2】:

如果您想动态创建数据库连接,请查看this SO 帖子。

来自链接的帖子:基本上在 JDBC 中,这些属性中的大多数是不可配置的 像这样的 API,而不是它们依赖于实现。 JDBC方式 处理此问题的方法是允许每个连接 URL 不同 供应商。

所以你要做的就是注册驱动,让JDBC系统知道 如何处理 URL:

DriverManager.registerDriver((Driver)
Class.forName("com.mysql.jdbc.Driver").newInstance());

然后你形成 网址:

String url =
 "jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"

最后,用它来建立连接:

Connection c = DriverManager.getConnection(url);

在更多 复杂的 JDBC,您会涉及到连接池和 喜欢,并且应用服务器通常有自己的注册方式 JNDI 中的驱动程序,然后从那里查找 DataSource,然后调用 getConnection 就可以了。

关于 MySQL 支持的属性,请参见此处(链接已失效)。

编辑:再想一想,从技术上讲,只有一行代码 Class.forName("com.mysql.jdbc.Driver") 应该足够了,因为 类应该有它自己的静态初始化器,它注册一个 版本,但有时 JDBC 驱动程序没有,所以如果您不确定, 注册第二个没有什么坏处,它只是创建了一个 内存中的重复对象。

我不知道这是否可行,因为我还没有测试过,但是你 可以试试。

现在您可以做的是,在 DAO 顶部使用 @Transactional 注释而不指定任何值(这有效)。现在在您的 DAO 类中,不要注入任何 DataSource bean,而是按照上面链接中的指定动态创建您自己的数据源,然后在运行时注入该依赖项,使用 getter setter 方法,或者只使用 new 关键字。我希望这样可以解决问题。

注意:我自己还没有测试过,所以如果可行,请告诉我。

【讨论】:

以上是关于spring 中的多个事务管理器,并在运行时选择一个的主要内容,如果未能解决你的问题,请参考以下文章

Swift中的多个pickerview didSelectRow错误

使用多个数据源时 Spring 中的多个实体管理器问题

Spring批处理中的多个项目编写器

jQuery Datepicker,选择多个日期并在选择时通过css标记它们,永久

Excel VBA - 从多个打开的文件资源管理器窗口中关闭特定的文件资源管理器窗口

C#:如何打开选择了多个文件的 Windows 资源管理器窗口