通过RestController从Spring CrudRepository流式传输

时间:2017-09-26 16:11:59

标签: java spring spring-data-jpa spring-restcontroller spring-webflux

我正在尝试通过RestController从CrudRepository传输大型数据集。我正在使用HSQLDB进行测试。然而,无论我做什么,我都无法使它发挥作用。首先我尝试使用流:

流尝试

存储库

public interface PersonRepository extends CrudRepository<Person, String> {

    @Query("select p from Person p")
    Stream<Person> streamAll();
}

RestController

@RestController
public class PersonRestController {

    @Autowired
    private PersonRepository personRepository;

    @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
    @GetMapping("stream")
    public StreamingResponseBody getPersonsStream() {

        return new StreamingResponseBody() {
            @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
            @Override
            public void writeTo(OutputStream outputStream) throws IOException {
                try (
                        PrintWriter writer = new PrintWriter(outputStream);
                        Stream<Person> stream = personRepository.streamAll()
                ) {
                    stream
                            .map(person -> person.getFirstName() + " " + person.getLastName())
                            .forEach(name -> {
                                writer.println(name);
                                writer.flush();
                            });
                }
            }
        };
    }
}

但它不起作用。无论我做什么,Spring都抱怨缺少只读事务。

然后我尝试使用WebFlux:

WebFlux尝试

存储库

public interface PersonRepository extends CrudRepository<Person, String> {

    @Query("select p from Person p")
    Flux<Person> fluxAll();

}

RestController

@RestController
public class PersonRestController {

    @Autowired
    private PersonRepository personRepository;

    @Transactional(readOnly = true)
    @GetMapping(value = "stream", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Flux<Person> getPersonsStream() {

        return personRepository.fluxAll();
    }
}

我来了

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.ArrayList<?>] to type [reactor.core.publisher.Flux<?>]

是否有一种通过RestController从存储库传输数据的简单方法?

2 个答案:

答案 0 :(得分:0)

在您的WebFlux尝试中,PersonRepository需要扩展ReactiveCrudRepository

答案 1 :(得分:0)

这就是我的成就。

存储库

@Query("SELECT c FROM Customer c")
@QueryHints(value = @QueryHint(name = HINT_FETCH_SIZE, value = "0"))
public Stream<Customer> streamAll();

服务

@Transactional(readOnly = true)
public void streamAll(final OutputStream outputStream) {
  try {
    final Stream<Customer> stream = customerRepository.streamAll();
    objectMapper.writeValue(outputStream, stream);
  } catch (Exception e) {
    log.error(e.getMessage(), e);
  }
}

控制器

@GetMapping("/stream")
@ResponseBody
public StreamingResponseBody streamAll() {
  return outputStream -> customerService.streamAll(outputStream);
}