java CrudRepository 在我的自定义存储库实现中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15124937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CrudRepository inside my custom repository implementation
提问by Julian B.
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
)的引用,该接口CrudRepository
在我的自定义实现 ( UserRepositoryExtensionImpl
) 中扩展,以便访问 Spring JPA 提供的所有方法。
Crud Extension:
原油扩展:
@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
). I am getting the following error:
但是,我无法注入,UserRepository
因为存在循环依赖(假设UserRepository
扩展了 my 实现的接口UserRepositoryImpl
)。我收到以下错误:
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
,但在这种情况下,我无权访问 提供的任何 Spring JPA 方法CrudRepository
,或我可能在 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
fromUserRepositoryExtensionImpl
- Renaming
UserRepositoryExtensionImpl
toUserRepositoryImpl
. Apparently this makes Spring aware of the implementation's existence. See Spring Doc - Removing my constructor and moving the
@Autowired
to theuserRepository
field
- 删除
@Repository
从UserRepositoryExtensionImpl
- 重命名
UserRepositoryExtensionImpl
为UserRepositoryImpl
. 显然,这使 Spring 意识到实现的存在。参见Spring 文档 - 删除我的构造函数并将其移动
@Autowired
到该userRepository
字段
SUCCESS!
成功!
采纳答案by shelley
A couple small things need to be changed in order for this to work:
需要更改一些小东西才能使其正常工作:
Remove the
@Repository
annotation from the custom repository interface (UserRepositoryExtension
).The custom repository implementation should actually be named "
<StandardRepository>Impl
" rather than "<CustomRepository>Impl
". In your code example, this should beUserRepositoryImpl
instead ofUserRepositoryExtensionImpl
.
@Repository
从自定义存储库界面 (UserRepositoryExtension
) 中删除注释。自定义存储库实现实际上应该命名为“
<StandardRepository>Impl
”而不是“<CustomRepository>Impl
”。在您的代码示例中,这应该是UserRepositoryImpl
而不是UserRepositoryExtensionImpl
.
回答by Olle89
As shelley pointed out, the naming is really important to make the autowire work. 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!!! Should be "ItemRepository"
OBS!!!应该是“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.
如果有人遇到类似问题,请按照以下链接中 spring 文档中使用的命名标准开始。
回答by Danila Piatov
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
}
}
回答by Przemek Nowak
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
它也不会工作(基本存储库的工厂 bean 会有问题)。
I think in this case the @Lazy
is the most elegant solution.
我认为在这种情况下,这@Lazy
是最优雅的解决方案。
回答by Michail Nikolaev
I have solved problem by injecting ApplicationContext
and getting bean in lazy way using applicationContext.getBean(UserRepository.class)
.
It works this way.
我已经通过ApplicationContext
使用applicationContext.getBean(UserRepository.class)
. 它是这样工作的。
回答by zagyi
There is a well defined way to create custom repository implementations in Spring Data JPAwhich you should follow. Basically you need to extend CrudRepository
so you don't have to inject an instance of it in your custom implementation.
在 Spring Data JPA中有一种定义明确的方法来创建自定义存储库实现,您应该遵循它。基本上你需要扩展,CrudRepository
这样你就不必在你的自定义实现中注入它的一个实例。