我们有一个web应用程序,它使用Spring事务管理和Hibernate多租户模式设置,其中租户基于请求URL进行解析。我想根据Web请求执行一些特定于租户的Spring批处理作业,在我的理解中,提供给Spring批处理的数据源无法识别租户并将作业实例数据插入到相应的租户模式中。我猜我们可以将租户ID添加到作业参数中,使其成为唯一的租户作业,驻留在默认模式中。但我的要求是将作业实例数据保留在租户特定的模式中,并根据租户ID获取作业和运行作业。非常感谢任何想法。
JobRepository
(将作业元数据读取/写入数据库的内容)在某种意义上是无状态的,如果您提供给它的DataSource
是租户感知的,则它会进入正确的模式。因此,你所需要做的就是为Spring Batch提供一个返回上下文正确连接的数据源。例如,确保数据源在返回连接之前将其设置为正确的模式。以下是一个示例:@Bean
@Scope(value='thread', proxyMode = ScopedProxyMode.INTERFACES)
DataSource dataSource() {
DataSource original = new JdbcDataSource(
url:'jdbc:h2:mem:temp_db;DB_CLOSE_DELAY=-1',
user: 'sa',
password: 'sa',)
new DataSource() {
@Delegate
DataSource delegate = original
@Override
Connection getConnection() throws SQLException {
String schema = schemaHolder().schema
original.connection.with {
it.createStatement().execute("SET SCHEMA $schema")
// in other databases, the syntax may be different, e.g.
//it.createStatement().execute("USE $schema")
it
}
}
@Override
Connection getConnection(String username, String password) throws SQLException {
connection
}
}
}
thread
范围来告诉每个线程应该使用哪个模式,但您可以使用任何方法来确定数据源中的正确模式。Caused by: org.springframework.dao.OptimisticLockingFailureException: Attempt to update step execution id=1 with wrong version (2), where current version is 1原因是Spring Batch确实有一个令人讨厌的全局状态--静态变量
StepSynchronizationManager.manager
包括一个名为contexts
的映射,其中它存储了所有当前活动的步骤执行上下文。这是一个键为StepExecution
的映射。 StepExecution :: equals
的定义方式使得具有相同作业实例ID,相同步骤名称和相同ID的两个实例将比较相等。如果您恰好同时运行具有相同(自动生成的)ID的两个作业,每个作业运行具有相同(自动生成的)ID和相同名称的两个步骤,则会遇到问题。在实际世界中,这种情况很不可能发生,但您应该意识到这一点。
@Delegate
只是以这样一种方式实现了DataSource
的其余方法,即将调用转发到delegate
。 - Artefacto