使用spring批处理时,我需要将数据写入两个不同的表。看起来我可以使用尽可能多CompositeItemWriter
的{{1}}。
但是,我需要在第一个表中插入一条记录并检索自动生成的主键,并在插入第二个表时使用它。 知道如何在这种情况下检索自动生成的密钥吗?
答案 0 :(得分:4)
威斯康星州'解决方案确实有效,但从您的性能角度来看(通常是讨论批处理时的主要问题之一),不推荐使用。
问题: 如何选择插入的行以读取生成的键? 你有另一个独特的领域,或者至少是它的组合,它可以让你识别书面项目? 你能把至少所有项目列表中的所有项目都读作一个单独的来电 db或者您是否必须使用自己的select?
读取每个条目至少,您将对数据库进行额外的读取调用。但它也可以是每个项目的额外电话。
更好的解决方案是能够在批处理中创建密钥。
如果我们只讨论几千个插页,性能可能不是问题。但是,如果我们谈论数百万,那就很重要。
无论如何,如果我真的不得不重新阅读db,我会使用以下两种方法。
首先,如果我不必在同一个交易中写两个表
第1步:
第2步:
其次,如果我必须在同一个事务中写两个表
public class MyWriter implements ItemWriter<MyObject> {
private JdbcItemWriter<MyObject> writer1;
private JdbcItemWriter<MyObject> writer2;
@PostConstruct
public void afterPropertiesSet() {
writer1 = new JdbcItemWriter<MyObject>();
writer1.set...
writer1.afterPropertiesSet();
writer2 = ... same thing
}
public void write(List<MyObject> items) {
writer1.write(items);
List<MyObject> reReadItems =
new JdbcTemplate(datasource)
// you could use a row that which has a unique chunk id
// or you could construct a query with an appropriate
// in-Clause... however, the size of possible in-clauses
// is limited, for instance oracle has 1000
.query(a query that selects only the entries you inserted above,
(resultset, row) -> // RowMapper
{
MyObject obj = new MyObject();
obj.setXy(resultset.get...);
...
return obj;
});
writer2.write(reReadItems);
}
}
这至少会限制你对数据库的调用,每个块的一次加法调用。
答案 1 :(得分:1)
编写器总是按顺序执行。因此,您可以写入第一个表并在第一个写入器中读取生成的键,并写入第二个写入器中的第二个表。如果您更新了第一个编写器中的对象,您将在第二个编写器中获得更新。
第一位作家可能看起来像:
public class MyWriter implements ItemWriter<MyObject> {
@Override
public void write(List<? extends MyObject> items) throws Exception {
// assuming there is a DB connection
for(MyObject item: items) {
// create and execute query to insert data in table 1
// get generated key and assign it into object
int key = rs.getInt(...);
item.setGeneratedKey(key);
}
}
}
第二个编写者可以使用generatedKey
字段来构造表2的查询。当您在第一个编写器中注入该值时,它将可供第二个编写者使用。
答案 2 :(得分:0)
我是Springby批量启动的新人。但是有很多大型机批处理经验。假设您已输入文件,我将以这种方式进行操作: 1-制作仅插入具有生成键的实体A的作业 2-制作作业(或步骤),以通过读取db扩展带有生成键的输入。输出=输入+生成的密钥 3-做插入你的实体B的工作 因此,请勿尝试一步之遥.....