我想要的:跳过春天用findAll(Pageable)
执行的计数查询。
我发现这些用户界面({next})有Slice
datatype,不需要总记录/页面,因此不需要计数查询。
我可以对Slice
等方法使用findByName(Pageable)
返回类型
但如果我使用Slice for findAll(Pageable),那么它仍会执行计数查询。
是否有一种解决方法,我可以使用切片findAll
来避免计数查询?
P.S。 :我想要切片提供的功能 - hasNext,size等 而且我也不需要使用规范。
感谢任何帮助。
答案 0 :(得分:1)
可以将Slice
与findAll()
一起使用-您只需要扩展正确的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);
}
}