query pagingandsortingrepository pageable framework findbyid data crudrepository java spring hibernate spring-mvc spring-data-jpa

java - pagingandsortingrepository - CrudRepository dentro de mi repositorio personalizado implementado



spring framework repository (6)

Estoy intentando obtener una referencia a mi interfaz de repositorio ( UserRepository ) que extiende CrudRepository dentro de mi implementación personalizada ( UserRepositoryExtensionImpl ) para obtener acceso a todos los métodos proporcionados por Spring JPA.

Extensión Crud:

@Repository public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser> { ...any custom spring JPA methods... }

Interfaz de extensión:

@Repository public interface UserRepositoryExtension <T> { public T put(T entity); }

Implementación personalizada:

public class UserRepositoryExtensionImpl implements UserRepositoryExtension<User> { UserRepository userRepository; @Autowired public UserRepositoryExtensionImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public User put(User user) { System.out.println(user + "was put"); // ...put logic here return null; }... }

Sin embargo, no puedo inyectar UserRepository debido a que existe una dependencia circular (dado que UserRepository extiende la interfaz implementada por mi UserRepositoryImpl ). Estoy teniendo el siguiente error:

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name '' userRepositoryImpl'': Requested bean is currently in creation: Is there an unresolvable circular reference?

Una solución posible, pero menos que ideal, sería inyectar EntityManager en UserRepositoryImp , pero en ese caso, no tengo acceso a ninguno de los métodos Spring JPA proporcionados por CrudRepository , ni a ningún otro método adicional que pueda haber creado en UserRepository.

¿Alguna sugerencia sobre cómo solucionar esto?

Cualquier ayuda sería muy apreciada.

EDITAR: Como se mencionó en la respuesta de @ shelley, pude resolver esto haciendo 3 cambios:

  • Eliminando el @Repository de UserRepositoryExtensionImpl
  • Renombrando UserRepositoryExtensionImpl a UserRepositoryImpl . Aparentemente esto hace que Spring sea consciente de la existencia de la implementación. Ver Spring Doc
  • Eliminando mi constructor y moviendo el @Autowired al campo userRepository

¡ÉXITO!


Bueno, en este caso sugiero usar la anotación @Lazy .

public class MyCustomRepositoryImpl implements MyCustomRepository { @Lazy @Autowired private MyRepository myRepository; @Override public boolean customMethod() { return myRepository.count() > 0; } }

Con el parámetro constructor, Spring intenta crear la clase de repositorio "básica" que requiere su repositorio personalizado, que requiere su repositorio "básico", el caso típico con dependencia circular.

Sin @Lazy pero solo con @Autowired tampoco funcionará (habrá un problema con el bean de fábrica para el repositorio básico).

Creo que en este caso el @Lazy es la solución más elegante.


Como Shelley señaló, el nombramiento es realmente importante para que el autowire funcione. En el siguiente ejemplo, sigo el estándar de nombres correcto para mi interfaz personalizada y su implementación. Pero mi interfaz que extendió JpaRepository se llamó "ItemDao" en lugar de "ItemRepository", esto dio como resultado que esa primavera ignoré por completo mi implementación personalizada ...

OBS !!! Debería ser "ItemRepository"

@Repository public interface ItemDao extends JpaRepository<Item, Long>, ItemRepositoryCustom {}

mi interfaz

interface ItemRepositoryCustom {...}

mi clase de implementación

class ItemRepositoryImpl implements ItemRepositoryCustom {...}

Si alguien tiene problemas similares, comience por seguir el estándar de denominación que se usa en la documentación de Spring en el enlace a continuación.

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations


Encontré una forma de hacerlo sin la necesidad de @Autowire :

public interface UserRepository extends UserRepositoryBasic, UserRepositoryExtension { } public interface UserRepositoryBasic extends JpaRepository<User, String> { // standard Spring Data methods, like findByLogin } public interface UserRepositoryExtension { public void customMethod(); } public class UserRepositoryExtensionImpl implements UserRepositoryExtension { private final UserRepositoryBasic userRepositoryBasic; // constructor-based injection public UserRepositoryExtensionImpl( UserRepositoryBasic userRepositoryBasic) { this.userRepositoryBasic = userRepositoryBasic; } public void customMethod() { // we can call all basic Spring Data methods using // userRepositoryBasic } }


Es necesario cambiar un par de cosas pequeñas para que esto funcione:

  • Elimine la anotación @Repository de la interfaz del repositorio personalizado ( UserRepositoryExtension ).

  • La implementación del repositorio personalizado en realidad debería llamarse " <StandardRepository>Impl " en lugar de " <CustomRepository>Impl ". En su ejemplo de código, esto debería ser UserRepositoryImpl lugar de UserRepositoryExtensionImpl .



He resuelto el problema inyectando ApplicationContext y obteniendo bean de forma perezosa utilizando applicationContext.getBean(UserRepository.class) . Funciona de esta manera.