Spring 批处理 - RepositoryItemReaderBuilder with RepositoryMethodReference throws Cannot subclass final class

Spring Batch - RepositoryItemReaderBuilder with RepositoryMethodReference throws Cannot subclass final class

我正在尝试使用 Spring 以 RepositoryMethodReference 作为参数的批处理 RepositoryItemReaderBuilder 来提供调用存储库方法的类型安全方式。

不幸的是我无法完成这项工作,因为这会抛出

java.lang.IllegalArgumentException: Cannot subclass final class com.sun.proxy.$Proxy100

据我了解,要使这个工作存储库不应该是最终的,但我该怎么做?

    implementation 'org.springframework.batch:spring-batch-core:4.3.5'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa:2.6.7'
@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String firstName;
    
    ...constructors, getters, setters
}

public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {

}
@SpringBootApplication
public class AccessingDataJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(AccessingDataJpaApplication.class);
    }

    @Bean
    public CommandLineRunner demo(CustomerRepository repository) {
        return (args) -> {
            
            Customer customer = new Customer();
            customer.setFirstName("John");
            repository.save(customer);

            RepositoryItemReaderBuilder.RepositoryMethodReference<CustomerRepository> repositoryMethodReference =
                    new RepositoryItemReaderBuilder.RepositoryMethodReference<>(repository);
            repositoryMethodReference.methodIs().findAll();

            RepositoryItemReader<Customer> reader = new RepositoryItemReaderBuilder<Customer>()
                    .repository(repositoryMethodReference)
                    .sorts(Collections.singletonMap("id", Sort.Direction.ASC))
                    .maxItemCount(5)
                    .name("bar").build();

            Customer read = reader.read();
        };
    }

}

解决方法是创建

public class PagingAndSortingRepositoryWrapper<T, ID> implements PagingAndSortingRepository<T, ID> {

    private PagingAndSortingRepository<T, ID> pagingAndSortingRepository;

    public PagingAndSortingRepositoryWrapper() {
    }

    public PagingAndSortingRepositoryWrapper(PagingAndSortingRepository<T, ID> pagingAndSortingRepository) {
        this.pagingAndSortingRepository = pagingAndSortingRepository;
    }

    @Override
    public Iterable<T> findAll(Sort sort) {
        return pagingAndSortingRepository.findAll(sort);
    }
    @Override
    public Page<T> findAll(Pageable pageable) {
        return pagingAndSortingRepository.findAll(pageable);
    }
    ...

那么 repositoryWrapper 将不是最终的,我们将能够使用 RepositoryMethodReference

PagingAndSortingRepositoryWrapper<Customer, Long> repositoryWrapper = new PagingAndSortingRepositoryWrapper<>(customerRepository);

        RepositoryItemReaderBuilder.RepositoryMethodReference<PagingAndSortingRepositoryWrapper> repositoryMethodReference =
                new RepositoryItemReaderBuilder.RepositoryMethodReference<>(repositoryWrapper);
        repositoryMethodReference.methodIs().findAll();

        RepositoryItemReader<Customer> itemReader = new RepositoryItemReaderBuilder<Customer>()
                .repository(repositoryMethodReference)
                .name("bar")
                .sorts(Collections.singletonMap("id", Sort.Direction.ASC))
                .build();