setMaxResults для аннотации Spring-Data-JPA? - PullRequest
105 голосов
/ 16 февраля 2012

Я пытаюсь включить Spring-Data-JPA в свой проект. Одна вещь, которая смущает меня, - как мне добиться setMaxResults (n) с помощью аннотации?

например, мой код:

public interface UserRepository extends CrudRepository<User , Long>
{
  @Query(value="From User u where u.otherObj = ?1 ")
  public User findByOhterObj(OtherObj otherObj);
}

Мне нужно только вернуть one (and only one) пользователя из otherObj, но я не могу найти способ аннотировать maxResults. Может кто-нибудь дать мне подсказку?

(MySQL жалуется:

com.mysql.jdbc.JDBC4PreparedStatement@5add5415: select user0_.id as id100_, user0_.created as created100_ from User user0_ where user0_.id=2 limit ** NOT SPECIFIED **
WARN  util.JDBCExceptionReporter - SQL Error: 0, SQLState: 07001
ERROR util.JDBCExceptionReporter - No value specified for parameter 2

)

Я нашел ссылку: https://jira.springsource.org/browse/DATAJPA-147, Я пытался, но не получилось. Кажется, сейчас это невозможно? Почему такая важная функция не встроена в Spring-Data?

Если я реализую эту функцию вручную:

public class UserRepositoryImpl implements UserRepository

Мне нужно реализовать множество предопределенных методов в CrudRepository, это было бы ужасно.

окружения: spring-3.1, spring-data-jpa-1.0.3.RELEASE.jar, spring-data-commons-core-1.1.0.RELEASE.jar

Ответы [ 7 ]

165 голосов
/ 16 февраля 2012

По состоянию на Spring Data JPA 1.7.0 (выпуск Эванса).

Вы можете использовать недавно введенные ключевые слова Top и First, которые позволяют вам определять методы запроса следующим образом:

findTop10ByLastnameOrderByFirstnameAsc(String lastname);

Spring Data автоматически ограничит результаты указанным вами числом (по умолчанию 1, если не указано). Обратите внимание, что здесь упорядочение результатов становится актуальным (либо с помощью предложения OrderBy, как показано в примере, либо путем передачи параметра Sort в метод). Подробнее об этом читайте в блоге, посвященном новым функциям выпуска релиза Spring Data Evans или в документации .

Для предыдущих версий

Для извлечения только фрагментов данных в Spring Data используется абстракция нумерации страниц, которая поставляется с интерфейсом Pageable на запрашивающей стороне, а также абстракция Page на стороне результатов. Так что вы можете начать с

public interface UserRepository extends Repository<User, Long> {

  List<User> findByUsername(String username, Pageable pageable);
}

и используйте его так:

Pageable topTen = new PageRequest(0, 10);
List<User> result = repository.findByUsername("Matthews", topTen);

Если вам нужно узнать контекст результата (какая это на самом деле страница? Это первая? Сколько всего?), Используйте Page в качестве типа возврата:

public interface UserRepository extends Repository<User, Long> {

  Page<User> findByUsername(String username, Pageable pageable);
}

Код клиента может сделать что-то вроде этого:

Pageable topTen = new PageRequest(0, 10);
Page<User> result = repository.findByUsername("Matthews", topTen);
Assert.assertThat(result.isFirstPage(), is(true));

Не то чтобы мы запускали проекцию подсчета фактического запроса, который будет выполнен, если вы используете Page в качестве типа возврата, так как нам нужно выяснить, сколько всего элементов в общей сложности для вычисления метаданных. Кроме того, убедитесь, что вы действительно оснастили PageRequest информацией для сортировки, чтобы получить стабильные результаты. В противном случае вы можете запустить запрос дважды и получить другие результаты, даже если данные не изменились.

91 голосов
/ 08 февраля 2016

Если вы используете Java 8 и Spring Data 1.7.0, вы можете использовать методы по умолчанию, если хотите объединить аннотацию @Query с настройкой максимальных результатов:

public interface UserRepository extends PagingAndSortingRepository<User,Long> {
  @Query("from User u where ...")
  List<User> findAllUsersWhereFoo(@Param("foo") Foo foo, Pageable pageable);

  default List<User> findTop10UsersWhereFoo(Foo foo) {
    return findAllUsersWhereFoo(foo, new PageRequest(0,10));
  }

}
27 голосов
/ 11 февраля 2015

Есть способ, которым вы можете предоставить эквивалент «a setMaxResults (n) by annotation», как показано ниже:

public interface ISomething extends JpaRepository<XYZ, Long>
{
    @Query("FROM XYZ a WHERE a.eventDateTime < :before ORDER BY a.eventDateTime DESC")
    List<XYZ> findXYZRecords(@Param("before") Date before, Pageable pageable);
}

Это должно помочь, когда в качестве параметра отправляется страница.Например, чтобы получить первые 10 записей, вам нужно установить pageable на это значение:

new PageRequest(0, 10)
21 голосов
/ 19 октября 2014

Использовать Spring Data Evans (1.7.0 RELEASE)

В новом выпуске Spring Data JPA с другим списком модулей под названием Evans имеется функцияиспользуя ключевые слова Top20 и First для ограничения результата запроса,

, чтобы вы могли теперь написать

List<User> findTop20ByLastname(String lastname, Sort sort);

или

List<User> findTop20ByLastnameOrderByIdDesc(String lastname);

или для одного результата

List<User> findFirstByLastnameOrderByIdDesc(String lastname);
12 голосов
/ 07 декабря 2016

Лучший выбор для меня - это нативный запрос:

@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);
4 голосов
/ 22 сентября 2017

Если ваш класс @Repository расширяется JpaRepository, вы можете использовать приведенный ниже пример.

int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();

getContent возвращает List<Transaction>.

4 голосов
/ 26 августа 2015

Это также возможно при использовании @QueryHints.Пример ниже использует org.eclipse.persistence.config.QueryHints # JDBC_MAX_ROWS

@Query("SELECT u FROM User u WHERE .....")
@QueryHints(@QueryHint(name = JDBC_MAX_ROWS, value = "1"))
Voter findUser();
...