Java 我的自定义存储库实现中的crudepository

Java 我的自定义存储库实现中的crudepository,java,spring,hibernate,spring-mvc,spring-data-jpa,Java,Spring,Hibernate,Spring Mvc,Spring Data Jpa,我试图获取对我的存储库接口(UserRepository)的引用,该接口在我的自定义实现(UserRepositoryExtensionImpl)中扩展了crudepository),以便访问Spring JPA提供的所有方法 积垢扩展: @Repository public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser>

我试图获取对我的存储库接口(
UserRepository
)的引用,该接口在我的自定义实现(
UserRepositoryExtensionImpl
)中扩展了
crudepository
),以便访问Spring JPA提供的所有方法

积垢扩展:

@Repository
public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser> {
    ...any custom spring JPA methods...
}
一个可能但不太理想的解决方案是将EntityManager注入到
UserRepositoryImp
中,但在这种情况下,我无法访问
Crudepository
提供的任何Spring JPA方法,或者我可能在UserRepository中创建的任何其他方法

有没有关于如何解决这个问题的建议

任何帮助都将不胜感激

编辑:正如@shelley的回答中所提到的,我可以通过做3个更改来解决这个问题:

  • UserRepositoryExtensionImpl
  • UserRepositoryExtensionImpl
    重命名为
    UserRepositoryImpl
    。显然,这让Spring意识到了实现的存在。看
  • 删除我的构造函数并将
    @Autowired
    移动到
    userRepository
    字段

成功

有一个你应该遵循的原则。基本上,您需要扩展
crudepository
,这样您就不必在自定义实现中插入它的实例。

为了使其工作,需要更改一些小事情:

  • 从自定义存储库界面(
    UserRepositoryExtension
    )中删除
    @Repository
    注释

  • 自定义存储库实现实际上应该命名为“
    Impl
    ”而不是“
    Impl
    ”。在代码示例中,这应该是
    UserRepositoryImpl
    ,而不是
    UserRepositoryExtensionImpl


我通过注入
ApplicationContext
并使用
ApplicationContext.getBean(UserRepository.class)
以惰性方式获取bean解决了这个问题。
它就是这样工作的。

正如shelley指出的,命名对于autowire的工作非常重要。在下面的示例中,我遵循自定义接口及其实现的正确命名标准。但是我扩展JpaRepository的接口被命名为“ItemDao”而不是“ItemRepository”,这导致spring完全忽略了我的自定义实现

OBS!!!应该是“ItemRepository”

我的实现类

class ItemRepositoryImpl implements ItemRepositoryCustom {...}
如果有人有类似的问题,请从下面链接的spring文档中使用的命名标准开始


我找到了一种方法,无需使用
@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
    }
}
公共接口UserRepository扩展
UserRepositoryBasic,
UserRepositoryExtension
{ 
}
公共接口UserRepositoryBasic扩展
JpaRepository
{
//标准Spring数据方法,如findByLogin
}
公共接口UserRepositoryExtension
{
公共方法();
}
公共类UserRepositoryExtensionImpl实现
UserRepositoryExtension
{
私有最终用户repositorybasic用户repositorybasic;
//基于构造函数的注入
公共用户RepositoryExtensionImpl(
UserRepositoryBasic用户RepositoryBasic)
{
this.userRepositoryBasic=userRepositoryBasic;
}
公共方法()
{
//我们可以使用
//userRepositoryBasic
}
}

在这种情况下,我建议使用
@Lazy
注释

public class MyCustomRepositoryImpl implements MyCustomRepository {

    @Lazy
    @Autowired
    private MyRepository myRepository;

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

}
通过构造函数参数,Spring尝试创建“基本”存储库类,该类需要自定义存储库,而自定义存储库则需要“基本”存储库,这是循环依赖的典型情况

如果没有
@Lazy
,但只有
@Autowired
它也不会工作(基本回购的工厂bean会有问题)


我认为在这种情况下,
@Lazy
是最优雅的解决方案。

如果没有任何实际的循环依赖关系(即:Spring会感到困惑,因为它认为您有许多类似类型的bean)。添加额外的限定符,如bean id,以便Spring知道要autowire的bean。为我们提供您的Spring应用程序context@gerrytan-我可能错了,但我确实认为存在循环依赖。仅供参考:同样的问题正在被引用,我认为OP正在采用这种方法,但希望在自定义存储库实现中使用标准存储库bean中的方法。@zagyi,Shelley是正确的。我正试图遵循Spring建议的非常相同的方法,这就是我发现自己处于当前位置的原因。为了使问题更清楚,我会在问题中添加更多细节。@shelley,@Julian:对不起,仔细重读这个问题后,很明显我对它有严重的误解。然而,我认为朱利安试图做的事情很奇怪。通常,它是一个服务类,您可以在其中注入存储库实例并实现调用一个或多个存储库操作的更高级别的方法。检查将
put()
的逻辑移到服务接口/类的更高级别是否更有意义。@zagyi-我明白你的意思。因为它是一个PUT(一个实际的HTTP方法),所以我觉得repo将是这种逻辑的最合适的地方。此外,如果我要这样做,这个类将是我的存储库的包装器(如果我错了,请纠正我),因此我必须为spring提供的所有方法编写包装器(这不是理想的IMHO)。但这将是一个可能的解决方案。实际上,我是通过遵循shelley的建议和一个更微妙的技巧来实现它的。如果那
put()
真的是一个HTTP请求处理程序,那么我认为在任何情况下都不应该将它放在存储库中。根据SpringWebApp的标准分层,它属于存储库(控制器)上方的第二层
@Repository
public interface ItemDao extends JpaRepository<Item, Long>, ItemRepositoryCustom {}
interface ItemRepositoryCustom {...}
class ItemRepositoryImpl implements ItemRepositoryCustom {...}
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
    }
}
public class MyCustomRepositoryImpl implements MyCustomRepository {

    @Lazy
    @Autowired
    private MyRepository myRepository;

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

}