我可以将Slice与findAll方法一起使用:Spring Data

时间:2016-10-25 11:36:20

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

我想要的:跳过春天用findAll(Pageable)执行的计数查询。

我发现这些用户界面({next})有Slice datatype,不需要总记录/页面,因此不需要计数查询。

我可以对Slice等方法使用findByName(Pageable)返回类型 但如果我使用Slice for findAll(Pageable),那么它仍会执行计数查询。

是否有一种解决方法,我可以使用切片findAll来避免计数查询?

P.S。 :我想要切片提供的功能 - hasNext,size等 而且我也不需要使用规范。

感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

可以将SlicefindAll()一起使用-您只需要扩展正确的Spring JPA存储库即可。

如果您扩展JpaRepository,它将无法正常工作,因为它扩展了PagingAndSortingRepository,并且分页存储库中已经定义了findAll(Pageable pageable)方法。

如果扩展CrudRepository,则可以在存储库中定义方法const request = require('request'); const fs = require('fs'); function postSimData() { let simData = fs.readFileSync('./sim_data.json', 'utf8'); var options = { // Change to whatever you need. url: "http://localhost:8080/post_sim_data", method: "POST", body: simData, headers: { 'Content-Type': 'application/json' } }; console.log('Posting sim data..'); request(options, function (error, response, body) { if (error) { console.error('error:', error); } else { console.log('Response: Headers:', response && response.headers); } }); } /* Post data every 60000 milliseconds (one minute) */ setInterval(postSimData, 60000);

答案 1 :(得分:0)

我在spring data jpa examples中找到了以下内容:

/**
 * Returns a {@link Slice} counting a maximum number of {@link Pageable#getPageSize()} users matching given criteria
 * starting at {@link Pageable#getOffset()} without prior count of the total number of elements available.
 * 
 * @param lastname
 * @param page
 * @return
 */
Slice<User> findByLastnameOrderByUsernameAsc(String lastname, Pageable page);

如果这与您正在进行的操作相符并且仍然进行计数选择,我认为这是一个错误,并提出spring-data的问题

答案 2 :(得分:0)

我有一个类似的要求,即必须跳过计数查询以获取性能好处,最后,实现了Slice<T>结果集构造的自定义实现,如下所示,它将提供Slice<T>支持的所有功能例如hasNext,大小。

  • 存储库类
@Repository
public class CommonRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public <T> Slice<T> findAll(Class<T> entityClass, Pageable pageable) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);
        Root<T> entityRoot = criteriaQuery.from(entityClass);
        criteriaQuery.select(entityRoot);
        TypedQuery<T> query = entityManager.createQuery(criteriaQuery);

//limit of the returning result
        int pageSize = pageable.getPageSize();
//calculating offset from page-number and page-size
        int offset = pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageSize : 0;
//https://github.com/spring-projects/spring-data-jpa/blob/48597dca246178c0d7e6952425004849d3fb02c0/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java#L156
// always fetch additional one element and skip it based on the pageSize to know hasNext value
        query.setMaxResults(pageSize + 1);
        query.setFirstResult(offset);
        List<T> resultList = query.getResultList();
        boolean hasNext = pageable.isPaged() && resultList.size() > pageSize;
        return new SliceImpl<>(hasNext ? resultList.subList(0, pageSize) : resultList, pageable, hasNext);
    }
}
  • 存储库测试类
/**
* This integration Test requires the following external dependencies to run:
* 1. MySQL
*/
@ActiveProfiles("test")
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommonRepositoryITest {
    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private PhotoRepository photoRepository = null;

    @Autowired
    private CommonRepository commonRepository = null;

    @Test
    public void findAllTest() {
        //Data Setup
        String title = "BATMAN";
        String size = "300*300";
        List<Photo> photos = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            Photo photo = Photo.builder().
            id(UUID.randomUUID().toString()).
            title(title).
            size("300*300").
            thumbnailUrl("http://localhost:8080/" + UUID.randomUUID().toString())
            .url("http://localhost:8080/" + UUID.randomUUID().toString()).
            build();
            photos.add(photo);
        }
        photoRepository.saveAll(photos);

        List<Photo> resultList = entityManager.createQuery("FROM Photo", Photo.class).
            getResultList();

        boolean hasNext;
        int pageNumber = 0;
        int limit = 25;
        Pageable pageRequest = PageRequest.of(pageNumber, limit);
        int itemsToAssert = 0;
        do {
            Slice<Photo> photos = commonRepository.findAll(Photo.class, pageRequest);
            hasNext = photos.hasNext();
            itemsToAssert = itemsToAssert + photos.getNumberOfElements();
            pageNumber++;
            pageRequest = PageRequest.of(pageNumber, limit);
        } while (hasNext);
        Assertions.assertEquals(resultList.size(), itemsToAssert);
    }
}