使用 Spring JdbcMetadataStore (Oracle) 时引发 DuplicateKeyException
DuplicateKeyException raised when using Spring JdbcMetadataStore (Oracle)
我当前的 file:inbound-channel-adapter 配置工作正常。我是 运行 多个服务器中的应用程序,只有一个在实际处理文件。数据库 table INT_METADATA_STORE 也更新成功。我面临的问题是其中一台服务器仍在尝试插入记录并引发以下异常:
org.springframework.messaging.MessagingException: nested exception is
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback;
SQL [INSERT INTO INT_METADATA_STORE(METADATA_KEY, METADATA_VALUE, REGION) SELECT ?, ?, ? FROM INT_METADATA_STORE WHERE METADATA_KEY=? AND REGION=? HAVING COUNT(*)=0];
ORA-00001: unique constraint (SMS_OWNER.INT_METADATA_STORE_PK) violated;
nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SMS_OWNER.INT_METADATA_STORE_PK) violated
我尝试过不同的隔离方式,但没有成功。这是否与我使用 XML 与 Spring 集成 + Java 时使用的事务管理器有关?请参阅下面的一些配置:
<int-file:inbound-channel-adapter directory="file:/tmp/input/" prevent-duplicates="true" filter="compositeFileListFilter">
<int:poller max-messages-per-poll="1" cron="*/10 * * * * *">
<int:transactional transaction-manager="transactionManager" isolation="READ_COMMITTED" timeout="5" />
</int:poller>
</int-file:inbound-channel-adapter>
和
@Configuration
@EnableTransactionManagement
public class MetadataStoreConfiguration {
@Value("${input.file.pattern:(DUMMY)(_).*\.(xml)}")
private String pattern;
@Bean
@Qualifier("fileSystemPersistentAcceptOnceFileListFilter")
public FileSystemPersistentAcceptOnceFileListFilter fileSystemPersistentAcceptOnceFileListFilter(final DataSource dataSource) {
return new FileSystemPersistentAcceptOnceFileListFilter(metadataStore(dataSource),"");
}
@Bean
@Qualifier("metadataStore")
public JdbcMetadataStore metadataStore(final DataSource dataSource) {
JdbcMetadataStore metadataStore = new JdbcMetadataStore(dataSource);
return metadataStore;
}
@Bean
public CompositeFileListFilter<File> compositeFileListFilter(FileSystemPersistentAcceptOnceFileListFilter fileSystemPersistentAcceptOnceFileListFilter) {
CompositeFileListFilter<File> filter = new CompositeFileListFilter<>(Arrays.asList(fileSystemPersistentAcceptOnceFileListFilter, new RegexPatternFileListFilter(pattern)));
return filter;
}
@Bean
@Primary
public PlatformTransactionManager transactionManager(final DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
我正在使用 Spring Boot 2.2.4.RELEASE、Java 8 和Oracle 作为数据库。任何帮助将不胜感激。
不,你的配置完全OK。这真的无关紧要,因为它在启动时只被读取一次。在运行时,您只有 bean,并且它们已正确连接。因此,可以在 Java 配置中使用 PlatformTransactionManager
和 compositeFileListFilter
,并将它们用作 XML 的参考。
我认为问题不在于交易。更重要的是,它们甚至看起来像工作!
您的两个事务都尝试插入但没有看到值。当然,其中一个在提交时没问题,但另一个失败了,因为该值已经插入。使用 IINSERT INTO .. SELECT ... HAVING
我们实现了当前事务的原子性。但它确实没有给我们机会避免提交冲突...
看起来我们的 JdbcMetadataStore.putIfAbsent()
应该改进以捕捉这个 SQLIntegrityConstraintViolationException
作为数据存在的事实和 return 当前值。
请提出 GH 问题,我们会考虑如何进行!
我当前的 file:inbound-channel-adapter 配置工作正常。我是 运行 多个服务器中的应用程序,只有一个在实际处理文件。数据库 table INT_METADATA_STORE 也更新成功。我面临的问题是其中一台服务器仍在尝试插入记录并引发以下异常:
org.springframework.messaging.MessagingException: nested exception is
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback;
SQL [INSERT INTO INT_METADATA_STORE(METADATA_KEY, METADATA_VALUE, REGION) SELECT ?, ?, ? FROM INT_METADATA_STORE WHERE METADATA_KEY=? AND REGION=? HAVING COUNT(*)=0];
ORA-00001: unique constraint (SMS_OWNER.INT_METADATA_STORE_PK) violated;
nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SMS_OWNER.INT_METADATA_STORE_PK) violated
我尝试过不同的隔离方式,但没有成功。这是否与我使用 XML 与 Spring 集成 + Java 时使用的事务管理器有关?请参阅下面的一些配置:
<int-file:inbound-channel-adapter directory="file:/tmp/input/" prevent-duplicates="true" filter="compositeFileListFilter">
<int:poller max-messages-per-poll="1" cron="*/10 * * * * *">
<int:transactional transaction-manager="transactionManager" isolation="READ_COMMITTED" timeout="5" />
</int:poller>
</int-file:inbound-channel-adapter>
和
@Configuration
@EnableTransactionManagement
public class MetadataStoreConfiguration {
@Value("${input.file.pattern:(DUMMY)(_).*\.(xml)}")
private String pattern;
@Bean
@Qualifier("fileSystemPersistentAcceptOnceFileListFilter")
public FileSystemPersistentAcceptOnceFileListFilter fileSystemPersistentAcceptOnceFileListFilter(final DataSource dataSource) {
return new FileSystemPersistentAcceptOnceFileListFilter(metadataStore(dataSource),"");
}
@Bean
@Qualifier("metadataStore")
public JdbcMetadataStore metadataStore(final DataSource dataSource) {
JdbcMetadataStore metadataStore = new JdbcMetadataStore(dataSource);
return metadataStore;
}
@Bean
public CompositeFileListFilter<File> compositeFileListFilter(FileSystemPersistentAcceptOnceFileListFilter fileSystemPersistentAcceptOnceFileListFilter) {
CompositeFileListFilter<File> filter = new CompositeFileListFilter<>(Arrays.asList(fileSystemPersistentAcceptOnceFileListFilter, new RegexPatternFileListFilter(pattern)));
return filter;
}
@Bean
@Primary
public PlatformTransactionManager transactionManager(final DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
我正在使用 Spring Boot 2.2.4.RELEASE、Java 8 和Oracle 作为数据库。任何帮助将不胜感激。
不,你的配置完全OK。这真的无关紧要,因为它在启动时只被读取一次。在运行时,您只有 bean,并且它们已正确连接。因此,可以在 Java 配置中使用 PlatformTransactionManager
和 compositeFileListFilter
,并将它们用作 XML 的参考。
我认为问题不在于交易。更重要的是,它们甚至看起来像工作!
您的两个事务都尝试插入但没有看到值。当然,其中一个在提交时没问题,但另一个失败了,因为该值已经插入。使用 IINSERT INTO .. SELECT ... HAVING
我们实现了当前事务的原子性。但它确实没有给我们机会避免提交冲突...
看起来我们的 JdbcMetadataStore.putIfAbsent()
应该改进以捕捉这个 SQLIntegrityConstraintViolationException
作为数据存在的事实和 return 当前值。
请提出 GH 问题,我们会考虑如何进行!