java - query - spring data jpa jpql
setMaxResults para Spring-Data-JPA anotaciĆ³n? (7)
Estoy tratando de incorporar Spring-Data-JPA a mi proyecto. Una cosa me confunde es cómo lograr setMaxResults (n) por anotación?
por ejemplo, mi código:
public interface UserRepository extends CrudRepository<User , Long>
{
@Query(value="From User u where u.otherObj = ?1 ")
public User findByOhterObj(OtherObj otherObj);
}
Solo necesito devolver one (and only one)
Usuario de otherObj, pero no puedo encontrar la manera de anotar los resultados máximos ... ¿Alguien puede darme una pista?
(mysql se queja:
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
)
Encontré un enlace: https://jira.springsource.org/browse/DATAJPA-147 , lo intenté pero fallé. Parece que no es posible ahora? ¿Por qué una característica tan importante no está integrada en Spring-Data?
Si implemento esta función de forma manual:
public class UserRepositoryImpl implements UserRepository
Tengo que implementar toneladas de métodos predefinidos en CrudRepository
, esto será terrible.
entornos: spring-3.1, spring-data-jpa-1.0.3.RELEASE.jar, spring-data-commons-core-1.1.0.RELEASE.jar
Usa Spring Data Evans (1.7.0 RELEASE)
el nuevo lanzamiento de Spring Data JPA con otra lista de módulos llamados Evans tiene la característica de usar palabras clave Top20
y First
para limitar el resultado de la consulta,
entonces ahora puedes escribir
List<User> findTop20ByLastname(String lastname, Sort sort);
o
List<User> findTop20ByLastnameOrderByIdDesc(String lastname);
o por un solo resultado
List<User> findFirstByLastnameOrderByIdDesc(String lastname);
A partir de Spring Data JPA 1.7.0 (tren de lanzamiento de Evans).
... puede usar las palabras clave Top
y First
recientemente introducidas que le permiten definir métodos de consulta como estos:
findTop10ByLastnameOrderByFirstnameAsc(String lastname);
Spring Data limitará automáticamente los resultados al número que definió (predeterminado a 1 si se omite). Tenga en cuenta que el orden de los resultados se vuelve relevante aquí (ya sea a través de una cláusula OrderBy
como se ve en el ejemplo o mediante la entrega de un parámetro Sort
en el método). Lea más al respecto en la publicación del blog que cubre las nuevas características del tren de lanzamiento de Spring Data Evans o en la documentation .
Para versiones anteriores
Para recuperar solo fragmentos de datos, Spring Data usa la abstracción de paginación que viene con una interfaz de página en el lado solicitante, así como una abstracción de Page
en el lado del resultado de las cosas. Entonces podrías comenzar con
public interface UserRepository extends Repository<User, Long> {
List<User> findByUsername(String username, Pageable pageable);
}
y úsalo así:
Pageable topTen = new PageRequest(0, 10);
List<User> result = repository.findByUsername("Matthews", topTen);
Si necesita conocer el contexto del resultado (¿qué página es en realidad ?, ¿es la primera? ¿Cuántos hay en total?) Use la Page
como tipo de devolución:
public interface UserRepository extends Repository<User, Long> {
Page<User> findByUsername(String username, Pageable pageable);
}
El código del cliente puede hacer algo como esto:
Pageable topTen = new PageRequest(0, 10);
Page<User> result = repository.findByUsername("Matthews", topTen);
Assert.assertThat(result.isFirstPage(), is(true));
No es que activaremos una proyección de recuento de la consulta real que se ejecutará en caso de que use la Page
como tipo de retorno, ya que necesitamos averiguar cuántos elementos hay en total para calcular los metadatos. Más allá de eso, asegúrese de equipar realmente PageRequest
con la información de clasificación para obtener resultados estables. De lo contrario, puede desencadenar la consulta dos veces y obtener resultados diferentes incluso sin que los datos hayan cambiado debajo.
Hay una forma en que puede proporcionar el equivalente a "un setMaxResults (n) por anotación" como en el siguiente:
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);
}
Esto debería ser el truco, cuando se envía un paginable como parámetro. Por ejemplo, para obtener los primeros 10 registros que necesita establecer paginable a este valor:
new PageRequest(0, 10)
La mejor opción para mí es la consulta nativa:
@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);
Si está utilizando Java 8 y Spring Data 1.7.0, puede usar métodos predeterminados si desea combinar una anotación @Query
con la configuración de los resultados máximos:
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));
}
}
Si su clase @Repository
extiende JpaRepository
, puede usar el ejemplo a continuación.
int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();
getContent devuelve una List<Transaction>
.
También es posible usar @QueryHints. El siguiente ejemplo utiliza 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();