我在应用程序中使用Spring JPA存储库和实体。现在,在该应用程序的风格中,我需要扩展我的一个实体并提供扩展存储库。
对于我需要覆盖/扩展的所有其他bean,我只需创建一个新实现并使用@Primary注释它,这样它就会被自动装配而不是默认实现。
但是,对于存储库,这不起作用。我可以使用@Primary注释新的存储库,但它没有任何效果(找到这两个bean,因此无法自动装配)。这是有道理的,因为存储库是一个接口而不是一个实现,实现是由Spring动态提供的。
我可以以某种方式告诉Spring(通过存储库或配置中的注释)使用哪个存储库?或者我是否必须像Using @Primary in Spring Data JPA repositories那样进行手动解决方法,还是应该提供一种存储库提供程序而不是自动装配?
修改以使事情变得更清晰:
假设我有一个实体A
@Entity
public class A {
@Id
private long id;
}
及其存储库
public ARepository extends Repository<A, Long> {
}
现在我将它扩展到实体B
@Entity
public class B extends A {
}
public interface BRepository extends ARepository {
}
通常,根据文档,您使用这样的存储库:
@Autowired
private ARepository repository;
然而,这确实不起作用,因为现在有两个ARepository
类型的bean。对于我自己实现的bean,我会在扩展类上使用@Primary
但是对于存储库,在编译时没有实现接口。
答案 0 :(得分:4)
我会根据这个答案改编这个想法:https://stackoverflow.com/a/27549198/280244和这个git示例https://github.com/netgloo/spring-boot-samples/tree/master/spring-boot-springdatajpa-inheritance/src/main/java/netgloo/models
引入一个标有@NoRepositoryBean
@NoRepositoryBean
public interface AbstractARepository<T extends A>
extends Repository<T, Long> {
T findByName(String name); //or what ever your queries are
}
public ARepository extends AbstractARepository<A> {
//almost emtpy
}
public BRepository extends AbstractARepository<B> {
//queries that are special for B
}
现在您可以注入ARepository
和BRepository
,两者都是类型保存!
答案 1 :(得分:1)
只是为了记录,可以按照此处的建议Using @Primary in Spring Data JPA repositories
向JPA存储库添加@Primary
支持
我对丢失代码的实现:
private boolean isSpringDataJpaRepository(Class<?> beanClass) {
return JpaRepositoryFactoryBean.class.isAssignableFrom(beanClass);
}
我认为@Ralph的答案因类型安全而更好。
答案 2 :(得分:0)
我能否以某种方式告诉 Spring(通过存储库上的注释或通过 配置)使用哪个存储库?
是的,你可以。首先,您为每个存储库类指定一个唯一的 bean 名称。
@Repository("myARepository")
public ARepository extends Repository<A, Long> {
}
@Repository("myBRepository")
public interface BRepository extends ARepository {
}
然后,当您使用 ARepository
作为类型自动装配时,您应该使用 @Qualifier
批注告诉 Spring 您想要哪个存储库。
@Autowire
@Qualifier("myBRepository")
private ARepository repository;
这将自动装配一个 BRepository