java - query - Spring Data JPA findOne() cambia a Opcional, ¿cómo usar esto?
spring data jpa jpql (4)
Api Optional
proporciona métodos para obtener los valores. Puede verificar la presencia del valor en isPresent()
y luego realizar una llamada para get()
o puede realizar una llamada para get()
encadenada con orElse()
y proporcionar un valor predeterminado.
Lo último que puedes hacer es usar @Query()
sobre un método personalizado.
Estoy aprendiendo SpringBoot2.0
con Java8
.
Y seguí algunos ejemplos de tutoriales para hacer blogs.
El código fuente del tutorial es:
@GetMapping("/{id}/edit")
public String edit(@PathVariable Long id, Model model) {
model.addAttribute("categoryDto", categoryService.findOne(id));
return "category/edit";
}
Pero este código está lanzando este error:
categoryService.findOne (id)
Estoy pensando en cambiar el findOne()
JPA findOne()
a Optional< S >
¿Cómo resolver eso?
Más información:
Este es el método categoryService:
public Category findOne(Long id) {
return categoryRepository.findOne(id);
}
De hecho, en la última versión de Spring Data, findOne devuelve un opcional. Si desea recuperar el objeto de la Opcional, simplemente puede usar get () en la Opcional. Sin embargo, en primer lugar, un repositorio debe devolver el opcional a un servicio, que luego maneja el caso en el que el opcional está vacío. después, el servicio debe devolver el objeto al controlador.
Desde al menos, la versión 2.0
, Spring-Data-Jpa
modificó findOne()
.
Ahora, findOne()
no tiene la misma firma y el mismo comportamiento.
Anteriormente, se definía en la interfaz CrudRepository
como:
T findOne(ID primaryKey);
Ahora, el único método findOne()
que encontrará en CrudRepository
es el que está definido en la interfaz QueryByExampleExecutor
como:
<S extends T> Optional<S> findOne(Example<S> example);
Eso se implementa finalmente con SimpleJpaRepository
, la implementación predeterminada de la interfaz CrudRepository
.
Este método es una consulta de búsqueda de ejemplo y no desea que sea reemplazado.
De hecho, el método con el mismo comportamiento sigue ahí en la nueva API, pero el nombre del método ha cambiado.
Se cambió el nombre de findOne()
a findById()
en la interfaz de CrudRepository
:
Optional<T> findById(ID id);
Ahora devuelve un Optional
. Que no es tan malo para evitar NullPointerException
.
Por lo tanto, el método real para invocar ahora es Optional<T> findById(ID id)
.
¿Cómo usar eso?
Aprendizaje de uso Optional
. Aquí información importante sobre su especificación:
Un objeto contenedor que puede o no contener un valor no nulo. Si hay un valor presente, isPresent () devolverá true y get () devolverá el valor.
Se proporcionan métodos adicionales que dependen de la presencia o ausencia de un valor contenido, como orElse () (devolver un valor predeterminado si el valor no está presente) e ifPresent () (ejecutar un bloque de código si el valor está presente).
Algunos consejos sobre cómo usar Optional
con Optional<T> findById(ID id)
.
Generalmente, cuando busca una entidad por id, desea devolverla o hacer un procesamiento particular si no se recupera.
Aquí hay tres ejemplos de uso clásico.
1) Supongamos que si se encuentra la entidad que desea obtener, de lo contrario, desea obtener un valor predeterminado.
Podrías escribir:
Foo foo = repository.findById(id)
.orElse(new Foo());
u obtenga un null
predeterminado null
si tiene sentido (el mismo comportamiento que antes del cambio de API):
Foo foo = repository.findById(id)
.orElse(null);
2) Suponga que si se encuentra la entidad que desea devolverla, de lo contrario, desea lanzar una excepción.
Podrías escribir:
return repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(id));
3) Suponga que desea aplicar un procesamiento diferente según si se encuentra la entidad o no (sin que sea necesario lanzar una excepción).
Podrías escribir:
Optional<Foo> fooOptional = fooRepository.findById(id);
if (fooOptional.isPresent()){
Foo foo = fooOptional.get();
// processing with foo ...
}
else{
// alternative processing....
}
El método ha sido renombrado a findById(…)
devolviendo un Optional
para que usted tenga que manejar la ausencia usted mismo:
Optional<Foo> result = repository.findById(…);
result.ifPresent(it -> …); // do something with the value if present
result.map(it -> …); // map the value if present
Foo foo = result.orElse(null); // if you want to continue just like before