2013-02-27 2 views
14

Я пытаюсь получить ссылку на мой репозиторий интерфейса (UserRepository), который расширяет CrudRepository в моей пользовательской реализации (UserRepositoryExtensionImpl) для того, чтобы получить доступ ко всем методам, предоставляемых Spring JPA.CrudRepository внутри моей пользовательской реализации хранилища

Crud Расширение:

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

Расширение интерфейса:

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

Пользовательские Реализация:

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; 
    }... 
} 

Однако, я не могу вводить UserRepository поскольку циклическая зависимость существует (при условии, что UserRepository расширяет интерфейс, реализованный мой UserRepositoryImpl). Я получаю следующее сообщение об ошибке:

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

Возможные, но меньше, чем идеальное решение было бы внедрить и EntityManager в UserRepositoryImp, но в этом случае, у меня нет доступа к какому-либо из методов Spring JPA, предоставляемых CrudRepository или любые дополнительные методы, которые я мог бы создать в UserRepository.

Любые предложения о том, как обойти это?

Любая помощь была бы принята с благодарностью.

EDIT: Как было сказано в ответ @ Shelley, я был в состоянии решить эту проблему, сделав 3 изменения:

  • Извлечение @Repository из UserRepositoryExtensionImpl
  • Переименование UserRepositoryExtensionImpl к UserRepositoryImpl. По-видимому, это заставляет Spring осознавать существование реализации. См Spring Doc
  • Удаление моего конструктора и перемещение @Autowired в userRepository поле

УСПЕХА!

+0

Если нет какой-либо фактическая циклической зависимости (то есть: Spring просто запутаться, потому что думает, что у вас есть много бобов подобного типа). Добавьте дополнительный определитель, такой как bean id, поэтому Spring знает, какой bean-компонент для autowire. – gerrytan

+0

дайте нам контекст приложения для вашего приложения – Elbek

+1

@gerrytan - Возможно, я ошибаюсь, но я думаю, что существует круговая зависимость. FYI: та же проблема упоминается [здесь] (http://forum.springsource.org/showthread.php?132889-Spring-Data-Calling-default-CRUD-methods-inside-a-custom-repository-implementation&p= 439701 # post439701) –

ответ

9

Пару мелких вещей, которые должны быть изменены для того, чтобы это работало:

  • Удалите @Repository аннотацию из интерфейса пользовательского хранилища (UserRepositoryExtension).

  • Реализация пользовательского хранилища фактически должна быть названа «<StandardRepository>Impl», а не «<CustomRepository>Impl». В вашем примере кода это должно быть UserRepositoryImpl вместо UserRepositoryExtensionImpl.

+0

Спасибо @shelley! Ваше предложение, в дополнение к перемещению '@ Autowired' из конструктора в поле' userRepository', решило проблему. Теперь я могу ссылаться на «UserRepository» в моей пользовательской реализации. :) –

0

Существует well defined way to create custom repository implementations in Spring Data JPA, за которым следует следовать. В основном вам необходимо расширить CrudRepository, поэтому вам не нужно вводить экземпляр его в свою пользовательскую реализацию.

+0

Я думаю, что OP следует этому подходу, но хотел бы использовать методы из стандартного компонента репозитория в рамках реализации пользовательского репозитория. – shelley

+0

@zagyi, Шелли верна. Я пытаюсь придерживаться того же подхода, который предлагает Spring, и именно так я оказался в позиции, в которой я нахожусь. Я добавлю больше деталей к вопросу, чтобы сделать проблему более ясной. –

+0

@shelley, @Julian: извините, после тщательного повторного чтения вопроса, ясно, что я плохо неправильно понял его. Однако я думаю, что это странно, что пытается сделать Джулиан. Обычно это класс обслуживания, в котором вы должны вводить экземпляры репозитория и внедрять методы более высокого уровня, которые вызывают одну или несколько операций репозитория. Проверьте, что было бы разумнее переместить логику 'put()' на один уровень выше в сервисный интерфейс/класс. – zagyi

0

Я решил проблему путем введения ApplicationContext и получить боб в ленивом способе, используя applicationContext.getBean(UserRepository.class). Он работает таким образом.

4

Как указывал шелли, наименования действительно важны для работы автошины. В приведенном ниже примере я следую правильному стандарту именования для моего пользовательского интерфейса и его реализации. Но мой интерфейс, который расширил JpaRepository, был назван «ItemDao» вместо «ItemRepository», это привело к тому, что весна вообще проигнорировала мою собственную реализацию ...

OBS !!! Должно быть «ItemRepository»

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

мой интерфейс

interface ItemRepositoryCustom {...} 

мой класс реализации

class ItemRepositoryImpl implements ItemRepositoryCustom {...} 

Если кто-нибудь есть подобные проблемы, начать следующий стандарт именования, который используется в документации яровой по ссылке ниже.

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

+1

Я хотел бы, чтобы такие детали были упомянуты более подробно ... Но, да, именование, по-видимому, очень важно. Рад, что ты тоже смог это понять! –

+1

Мне, когда вы читаете раздел документации без предварительного весеннего знания, нет никакого способа выяснить, насколько строгое правило именования. – Olle89

Смежные вопросы