使用Spring Batch作业加载数据时如何避免重复值?

时间:2019-04-23 19:26:51

标签: spring oracle spring-batch

我有一个Spring Batch程序,该程序从一个数据库读取数据,然后处理数据,然后写入Oracle数据库。该批处理程序每​​天按计划运行一次。如何避免每次运行时都添加相同的记录,而只添加源数据库中的新值?

4 个答案:

答案 0 :(得分:1)

一种选择是创建唯一索引(或主键,如果可能的话(取决于您是否允许空值)),这将导致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不会插入其列值已存在于目标表中的行。

答案 1 :(得分:1)

听起来您担心不多次处理同一张源记录。如果是这种情况,您可以在源表上添加一个字段,指示已提取数据。

哦,-在表上放一个唯一的主键。他们全部。甚至那些您认为不需要的地方。今天添加的主键是您以后不会说的“该死。我希望该表具有主键”。 Don't ask me how I know...

好运。

答案 2 :(得分:0)

我猜您正在使用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");

希望有帮助

答案 3 :(得分:0)

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

修改弹簧注释。

@Modifying
@Query(value = "insert into  T_UNIQUE_VALUE values(:a,:b,:c)  LOG ERRORS REJECT LIMIT UNLIMITED",  nativeQuery = true)
void insert_balbla(...)