【发布时间】:2019-04-23 19:26:51
【问题描述】:
我有一个 spring 批处理程序,它从一个数据库读取数据,然后处理数据,然后写入 Oracle 数据库。该批处理程序每天按计划运行一次。如何避免每次运行时都添加相同的记录,并且只添加源数据库中的新值?
【问题讨论】:
标签: spring oracle spring-batch
我有一个 spring 批处理程序,它从一个数据库读取数据,然后处理数据,然后写入 Oracle 数据库。该批处理程序每天按计划运行一次。如何避免每次运行时都添加相同的记录,并且只添加源数据库中的新值?
【问题讨论】:
标签: spring oracle spring-batch
一种选择是创建唯一索引(或主键,如果可能(取决于您是否允许空值)),这将导致 Oracle 自动拒绝其列违反唯一性的所有行。
其他选项需要一些编程。
[编辑:“静默”跳过错误]
这就是我的意思:
for cur_r in (select col1, col2
from another_table@db_link)
loop
begin --> you need inner BEGIN-EXCEPTION-END block
insert into new_table (col1, col2)
values (cur_r.col1, cur_r.col2);
exception
when dup_val_on_index then
null;
end;
end loop;
另一个选项使用纯 SQL(即没有 PL/SQL 的 循环):
insert into new_table (col1, col2)
select col1, col2
from another_table@db_link
where (col1, col2) not in (select col1, col2
from new_table);
此选项甚至不需要唯一索引(但这不会造成损害),因为NOT IN 不会插入其列值已存在于目标表中的行。
【讨论】:
create unique index ui_dept on dept (deptno, dname, loc)
您似乎担心不会多次处理相同的源记录。如果是这种情况,您可以在 源表 上添加一个字段,指示数据已被提取。
哦,而且 - 在您的表上放置一个唯一的主键。他们全部。即使是那些你认为你不需要它的地方。您今天添加的主键是您以后不会说的那个,“该死。我希望那个表有一个主键”。 Don't ask me how I know...
祝你好运。
【讨论】:
我猜你正在使用 RepositoryItemReader 作为源。如果是这种情况,您可以使用 @Query 在源存储库中添加自定义方法,包括验证条件以避免已处理的记录,然后在 RepositoryItemReader 中使用该方法。
应该是这样的
@Query("SELECT r FROM Records r WHERE r.isNew = 1")
Collection<Record> findAllNewRecords();
然后像这样配置阅读器
RepositoryItemReader<Record> recordsReader = new RepositoryItemReader<>();
recordsReader.setRepository(recordsRepository);
recordsReader.setMethodName("findAllNewRecords");
希望对你有帮助
【讨论】:
create table T_UNIQUE_VALUE( a number,b number, c varchar2(100));
alter table T_UNIQUE_VALUE ADD CONSTRAINT C_UNIQUE_VALUE UNIQUE (a,b);
定义日志错误表。 Oralce 将创建err$_table_name
BEGIN
DBMS_ERRLOG.create_error_log(dml_table_name => 'T_UNIQUE_VALUE');
END;
测试一下。
execut 2 times
insert into T_UNIQUE_VALUE values(1,1,'a') LOG ERRORS REJECT LIMIT UNLIMITED;
--check table T_UNIQUE_VALUE and err$_T_UNIQUE_VALUE
select * from err$_T_UNIQUE_VALUE; -- 1 row
select * from T_UNIQUE_VALUE; -- 1 row
修改spring注解。
@Modifying
@Query(value = "insert into T_UNIQUE_VALUE values(:a,:b,:c) LOG ERRORS REJECT LIMIT UNLIMITED", nativeQuery = true)
void insert_balbla(...)
【讨论】: