简体   繁体   English

我的自定义存储库实现中的CrudRepository

[英]CrudRepository inside my custom repository implementation

I am attempting to get a reference to my repository interface ( UserRepository ) that extends CrudRepository within my custom implementation ( UserRepositoryExtensionImpl ) in order to gain access to all the methods provided by Spring JPA. 我试图获得对我的存储库接口( UserRepository )的引用,该接口在我的自定义实现( UserRepositoryExtensionImpl )中扩展CrudRepository ,以便获得对Spring JPA提供的所有方法的访问。

Crud Extension: Crud扩展:

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

Extension Interface: 扩展接口:

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

Custom Implementation: 定制实施:

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

However, I am unable to inject UserRepository since a circular dependency exists (given that UserRepository extends the interface implemented by my UserRepositoryImpl ). 但是,我无法注入UserRepository因为存在循环依赖(假设UserRepository扩展了我的UserRepositoryImpl实现的接口)。 I am getting the following error: 我收到以下错误:

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

A possible, but less than ideal solution would be to inject and EntityManager into UserRepositoryImp , but in that case, I do not have access to any of the Spring JPA methods provided by CrudRepository , or any additional methods that I might have created in UserRepository. 一个可能但不太理想的解决方案是将EntityManager注入UserRepositoryImp ,但在这种情况下,我无法访问CrudRepository提供的任何Spring JPA方法,或者我可能在UserRepository中创建的任何其他方法。

Any suggestions on how to get around this? 有关如何绕过这个的任何建议?

Any help would be greatly appreciated. 任何帮助将不胜感激。

EDIT: As mentioned in @shelley's answer, I was able to solve this by making 3 changes: 编辑:正如在@ Shelley的回答中提到的,我能够通过进行3次更改来解决这个问题:

  • Removing the @Repository from UserRepositoryExtensionImpl 卸下@RepositoryUserRepositoryExtensionImpl
  • Renaming UserRepositoryExtensionImpl to UserRepositoryImpl . UserRepositoryExtensionImpl重命名为UserRepositoryImpl Apparently this makes Spring aware of the implementation's existence. 显然,这使得Spring意识到实现的存在。 See Spring Doc Spring Doc
  • Removing my constructor and moving the @Autowired to the userRepository field 删除我的构造函数并将@Autowired移动到userRepository字段

SUCCESS! 成功!

A couple small things need to be changed in order for this to work: 为了实现这一点,需要更改几件小事:

  • Remove the @Repository annotation from the custom repository interface ( UserRepositoryExtension ). 取下@Repository从定制库接口(注释UserRepositoryExtension )。

  • The custom repository implementation should actually be named " <StandardRepository>Impl " rather than " <CustomRepository>Impl ". 自定义存储库实现实际上应该命名为“ <StandardRepository>Impl ”而不是“ <CustomRepository>Impl ”。 In your code example, this should be UserRepositoryImpl instead of UserRepositoryExtensionImpl . 在您的代码示例中,这应该是UserRepositoryImpl而不是UserRepositoryExtensionImpl

As shelley pointed out, the naming is really important to make the autowire work. 正如Shelley指出的那样,命名对于使autowire工作非常重要。 In the example below, I follow the right naming standard for my custom interface and its implementation. 在下面的示例中,我遵循自定义界面及其实现的正确命名标准。 But my interface that extended the JpaRepository was named “ItemDao” instead of “ItemRepository”, this resulted in that spring ignored my custom implementation altogether... 但我扩展JpaRepository的界面被命名为“ItemDao”而不是“ItemRepository”,这导致Spring完全忽略了我的自定义实现......

OBS!!! OBS! Should be "ItemRepository" 应该是“ItemRepository”

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

my interface 我的界面

interface ItemRepositoryCustom {...}

my implementation class 我的实现类

class ItemRepositoryImpl implements ItemRepositoryCustom {...}

If anyone have similar problems, start by following the naming standard that is used in the spring documentation at the link below. 如果有人遇到类似问题,请首先遵循以下链接中弹簧文档中使用的命名标准。

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

There is a well defined way to create custom repository implementations in Spring Data JPA which you should follow. 有一种定义明确的方法可以在Spring Data JPA中创建自定义存储库实现 ,您应该遵循这些方法。 Basically you need to extend CrudRepository so you don't have to inject an instance of it in your custom implementation. 基本上你需要扩展CrudRepository这样你就不必在自定义实现中注入它的实例。

I have solved problem by injecting ApplicationContext and getting bean in lazy way using applicationContext.getBean(UserRepository.class) . 我通过使用applicationContext.getBean(UserRepository.class)注入ApplicationContext并以懒惰的方式获取bean来解决问题。 It works this way. 它以这种方式工作。

I found I way of how to do it without the need for @Autowire : 我找到了如何在不需要@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
    }
}

Well in this case I suggest to use the @Lazy annotation. 那么在这种情况下我建议使用@Lazy注释。

public class MyCustomRepositoryImpl implements MyCustomRepository {

    @Lazy
    @Autowired
    private MyRepository myRepository;

    @Override
    public boolean customMethod() {
       return myRepository.count() > 0;
    }

}

With constructor parameter Spring tries to create the "basic" repository class which require you custom repository which requires you "basic" repository - the typical case with circular dependency. 使用构造函数参数Spring尝试创建“基本”存储库类,它需要您自定义存储库,这需要您“基本”存储库 - 典型的循环依赖情况。

Without @Lazy but with only the @Autowired it also won't work (there will be problem with factory bean for the basic repo). 没有@Lazy但只有@Autowired它也不会工作(基本@Lazy工厂bean会有问题)。

I think in this case the @Lazy is the most elegant solution. 我想在这种情况下@Lazy是最优雅的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM