使用弹簧批处理作业加载数据时,如何避免重复值?

问题描述 投票:0回答:4

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

spring oracle spring-batch
4个回答
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
投票

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

哦,并且 - 在你的桌子上放一个独特的主键。他们都是。即使是那些你认为不需要它的人。你今天添加的主键是你以后不会说的那句话,“该死的。我希望那张表有一个主键”。 Don't ask me how I know...

祝你好运。


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");

希望能帮助到你


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);

定义日志错误表。 Oracle将创建qazxsw poi

err$_table_name

测试一下。

BEGIN 
   DBMS_ERRLOG.create_error_log(dml_table_name => 'T_UNIQUE_VALUE'); 
END;

修改spring注释。

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
© www.soinside.com 2019 - 2024. All rights reserved.