我想知道,是否建议使用这种方法来实现带jpa的reader spring批处理,还是寻找其他解决方案更好?如果不建议使用这种方法,我在哪里可以找到关于更好选项的信息

public class CreditCardItemReader implements ItemReader<CreditCard> {

@Autowired
private CreditCardRepository respository;

private Iterator<CreditCard> usersIterator;

@BeforeStep
public void before(StepExecution stepExecution) {
    usersIterator = respository.someQuery().iterator();
}

@Override
public CreditCard read() {
    if (usersIterator != null && usersIterator.hasNext()) {
        return usersIterator.next();
    } else {
        return null;
    }
}
  }

推荐答案

这种实现只适用于小数据集,因为数据通过一次批处理查询读取,并将整个结果列表存储在内存中.而且,它不是线程安全的.

  • 在内存有限的环境中可能会导致内存不足
  • 可能会导致性能问题.我们将等待,直到通过一次调用从DB加载数千条记录


Solution 1, 100

    protected void doOpen() throws Exception {
        ...
        Query query = createQuery();
        if (this.parameterValues != null) {
            this.parameterValues.forEach(query::setParameter);
        }
        this.iterator = query.getResultStream().iterator();
    }

例如,Hibernate在5.2版中引入了Query.getResultStream()方法.

    protected ItemReader<Foo> getItemReader() throws Exception {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        String jpqlQuery = "from Foo";
        JpaCursorItemReader<Foo> itemReader = new JpaCursorItemReader<>();
        itemReader.setQueryString(jpqlQuery);
        itemReader.setEntityManagerFactory(factoryBean.getObject());
        itemReader.afterPropertiesSet();
        itemReader.setSaveState(true);
        return itemReader;
    }

Solution 2, 100

ItemReader用于读取建立在JPA之上的数据库记录.

它执行JPQL setQueryString(字符串)以检索请求的

分页的性能取决于JPA实现和

设置相当大的页面大小并使用提交间隔

为了减少大结果的内存使用,持久性

在调用之间,实现是线程安全的

Solution 3, 100

一种项目阅读器,利用

读卡器的性能取决于存储库

必须为读卡器配置分页和排序存储库

此实现在调用之间是线程安全的

创建示例:

PagingAndSortingRepository<Foo, Long> repository = FooRepository<>();
RepositoryItemReader<Foo> reader = new RepositoryItemReader<>();
reader.setRepository(repository ); //The PagingAndSortingRepository implementation used to read input from.
reader.setMethodName("findByName"); //Specifies what method on the repository to call.
reader.setArguments(arguments); // Arguments to be passed to the data providing method.

通过生成器创建:

PagingAndSortingRepository<Foo, Long> repository = new FooRepository<>();
new RepositoryItemReaderBuilder<>().repository(repository)
                                   .methodName("findByName")
                                   .arguments(new ArrayList<>())
                                   .build()

更多用法示例:RepositoryItemReaderTestsRepositoryItemReaderIntegrationTests

Summarise:

Java相关问答推荐

Log4j2 JDBC Appender PoolingDriver 配置

java.lang.reflect.InaccessibleObjectException:无法使字段私有最终 java.util.Comparator java.util.TreeMap.comparator 可访问

正确显示货币 TWD

Jackson Parsing of Date 在某些机器上失败

在 Stream.map() 中转换为 (char) 不会产生所需的结果

如何判断 JDK 17 应用程序启动时 JVM 实际加载了哪些 JNI 库?

正则表达式在我的字符串中找不到最后一个词

是否可以从 OkHttp 解决 org.jetbrains.kotlin:kotlin-stdlib 漏洞?

Moshi 无法使用值列表反序列化 Map,返回 LinkedHashTreeMap 而不是值的类实例

如何只跳过java流中的第n个元素

如何在我的文件系统上添加一个 java gradle 项目作为对另一个本地项目的依赖?

使用不存在的产品下订单

OOME发生JVM退出时如何打印jfr?

需要 Class 时如何避免使用原始类型作为泛型参数

为什么 Java 中的非线程安全计数器总是返回正确的值?

过滤器上的流图

为什么在顺序一致的执行中没有数据竞争足以保证在所有执行中都不会出现数据竞争?

如何让 Jackson 将构造函数字段名称识别为没有显式 JsonProperty 的属性?

从原始@Transactional 方法调用@Transactional 方法导致同一类中的回滚问题

javax.validation.constraints.NotNull 不适用于 Kotlin 中的 java.time.Instant