Я разрабатываю серверное приложение на Spring Boot 2 и Croud Repository.
У меня есть таблица с названием MoneyTransfer, а в таблице есть столбцы с именами customerId и firmId.
Мне нужно получить последние 10 разных фирм, которым клиент переводил деньги.
В настоящее время я получаю от пользователей все денежные переводы и фильтрую их. Однако этот метод не имеет смысла, потому что я получаю все элементы в базе данных для поиска последних 10. Это может вызвать проблемы с производительностью.
fun getList(customerId: String) {
var list = mutableListOf<MoneyTransfer>()
moneyTransferRepository.findByCustomerId(customerId).forEach {
if (list.find(elem -> it.firmId == elem.firmId) == null) {
list.add(it)
}
if (list.size == 10) {
return@forEach
}
}
return list
}
Есть ли у вас какое-либо эффективное решение, которое позволило бы мне получить последние 10 различных идентификаторов компании, не получая всю строку базы данных?


Если вы используете Spring Data вместе с Spring Boot, вы можете создать SQL-запрос для получения только нужных вам записей и использовать его с аннотациями @Query.
Например:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
Документация здесь: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
Попробуйте так (не уверен - сейчас не могу протестировать)
public interface MoneyTransferRepository extends JpaRepository<MoneyTransfer, Long> {
MoneyTransfer findFirst10ByCustomerIdDesc(String customerId);
}
И отсортировать результат в обратном порядке в методе getList
Создайте собственный @Query с разбивкой на страницы, это поможет вам оптимизировать запрос, не получая всю строку базы данных.
@Repository
public interface MoneyTransferRepository extends CrudRepository<MoneyTransfer, String> {
@Query("SELECT m.firmId FROM MoneyTransfer m WHERE m.customerId = :customerId ORDER BY m.id DESC")
List<String> findFirmIdsByCustomerId(@Param("customerId") String customerId, Pageable pageable);
}
Но вам все равно придется проверять результат с помощью отличного firmId и проверять размер результата отличного firmIds, если он меньше 10, то в вашем случае вы снова сделаете запрос к базе данных и замените page в PageRequest.
moneyTransferRepository.findFirmIdsByCustomerId(customerId, PageRequest.of(0, 10));
P.S. Я также пробовал это с DISTINCT, но он игнорирует все дублированные firmId с тем же customerId
Спасибо. Но, наверное, я не мог объяснить проблему. Мне нужно получить 10 разных идентификаторов фирм. Чтобы получить это, мне, возможно, нужно проверить 15 рядов. Есть ли способ получить это.
Я думаю, вы можете попробовать изменить тип возвращаемого метода List <String> на Set <String> и получить PageRequest с размером 15, тогда, если размер списка> = 10, получить subList или получить следующую страницу из PageRequest и объединить с предыдущим результатом
Спасибо. Итак, как я могу получить последние 10 разных записей, для которых указан customerId? Какой запрос возвращает этот результат