有没有办法使用 Spring Boot 自动配置注册存储库基类?

Posted

技术标签:

【中文标题】有没有办法使用 Spring Boot 自动配置注册存储库基类?【英文标题】:Is there a way to register a repository base class with a spring boot auto configuration? 【发布时间】:2017-06-27 05:53:45 【问题描述】:

我们有一个基本的 JPA 存储库类,其中包含一些我们在项目中使用的附加实用程序方法。在Spring Data JPA documentation 之后,我们创建了类并在配置类中使用@EnableJpaRepositories 注解,如下例所示:

@Configuration
@EnableJpaRepositories(basePackageClasses = MyApplication.class,
    repositoryBaseClass = MyJpaRepositoryImpl.class)
public class SpringDataJpaMyRepositoryConfiguration 

我们还设置了 basePackageClasses 属性,以便找到我们的存储库,因为配置类不在应用程序根包中。一切都按预期工作,所以到目前为止没有问题。

现在我们想创建一个 spring boot starter 来将存储库基类添加到我们的项目中,而无需进一步配置,但我们不知道该怎么做。如果我们创建一个带有 EnableJpaRepositories 注释并设置 repositoryBaseClass 属性的 AutoConfiguration 类,自动存储库查找策略会在使用 @SpringBootApplication 注释的类下查找存储库em> 不再起作用了。

而且我们不能使用 basePackageClasses 属性,因为我们不知道使用自动配置的项目的主类或包。

有没有办法做到这一点?也许通过在我们的自动配置中重新定义一些 bean?

理想的方法是允许设置存储库基类,而不必再次定义所有 Spring Data JPA 自动配置。

【问题讨论】:

我遇到了同样的问题,仍在寻找解决方案。很遗憾,rdlopes 和 dan.jones 提供的答案并没有解决问题。 【参考方案1】:

这个问题当时把我逼疯了,所以我想我可以帮助你。

基本上,这个想法是:

为您的 Jpa 配置创建一个配置类 添加 @EntityScan 和 @EnableJpaRepositories 引用与 basePackageClass 相同的配置类 在您的自动配置中导入此配置类 创建一个注释,然后您可以在需要 Jpa 配置的地方重复使用该注释

在您的示例中,您使用 Spring 应用程序类作为扫描的基础。

我已经在https://github.com/rdlopes/custom-jpa-demo 提出了一个示例项目来 POC 主要思想

在示例中,有一个 JPA 实体/存储库项目公开了 JPA 配置:

   @Configuration
   @EntityScan(basePackageClasses = JpaConfiguration.class)
   @EnableJpaRepositories(basePackageClasses = JpaConfiguration.class,
                          repositoryBaseClass = BaseRepositoryImpl.class)
   public class JpaConfiguration 

   

小心你的仓库的通用实现,你需要显示一个特殊的签名:

@NoRepositoryBean
public class BaseRepositoryImpl<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID>
        implements BaseRepository<T, ID> 

    public BaseRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) 
        super(entityInformation, entityManager);
    

    @Override
    public String someCustomMethod(ID id) 
        return "Class for entity of id " + id + " is: " + getDomainClass().getSimpleName();
    

然后您可以像这样创建您的自动配置:

@Configuration
@ConditionalOnClass(CustomJpaRepositories.class)
@Import(JpaConfiguration.class)
public class JpaCustomAutoConfiguration 


提供注释以保持整洁并在需要 JPA 的地方使用它:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface CustomJpaRepositories 

使用您的 JPA 类就像在调用 JPA 存储库时使用此注释一样简单:

@SpringBootApplication
@CustomJpaRepositories
public class CustomJpaSampleApplication 

    public static void main(String[] args) 
        SpringApplication.run(CustomJpaSampleApplication.class, args);
    

    @Bean
    public CommandLineRunner dataInitializer(UserRepository userRepository) 
        return args -> 
            User user1 = new User();
            user1.setName("user 1");
            userRepository.save(user1);

            User user2 = new User();
            user2.setName("user 2");
            userRepository.save(user2);

            userRepository.findAll()
                          .forEach(user -> System.out.println(
                                  userRepository.someCustomMethod(user.getId())));
        ;
    

希望这可以帮助您度过令人头疼的时刻:-)

【讨论】:

感谢 Rui,提供信息和示例项目。然而,这并不是我们真正需要解决的。我们不在提供基础存储库类的库中提供实体和存储库,它们应该包含在每个项目中。但是您可以轻松地在您的示例项目中重现我们的场景,只需将 User 实体和 UserRepositorycustom-jpa 模块移动到 custom-jpa 模块i>custom-jpa-demo 模块。您是否偶然解决了这种情况? 目前还不清楚什么可以改变,什么不能改变。例如,您可以想象通过自动装配将您的实用程序注入自定义存储库。您还可以在自动配置中使用不同的 @Configuration 来引用一组不同的 bean 并使用组合模式。问题是我们没有针对您的问题的清晰架构,我想这就是为什么其他答案也不符合您的要求的原因。 我很乐意回答您的任何疑问或添加更多信息。另一个答案几乎走上了正轨,唯一的问题是它没有解决不需要在应用程序中进行任何进一步配置的要求。我认为这个要求是很难解决的。【参考方案2】:

编辑:我几乎重写了我的答案 - 我误解了原来的问题

这不是最好的解决方案,但我可以看到这个工作的唯一方法是在 @EnableJpaRepositories 中使用 SpEL。

这可以进入您的自动配置并使用@ConditionalOnProperty 仅在设置了基本包属性时才自动配置

@Configuration
@ConditionalOnProperty("repositories-base-packages")
public class BaseRepositoryAutoConfiguration 

    @Configuration
    @EnableJpaRepositories(
            repositoryBaseClass = MyJpaRepositoryImpl.class,
            basePackages = "$repositories-base-packages"
    )
    public static class JpaRepositoriesConfig  


然后确保您有一个 application.propertiesapplication.yml 在您的应用程序中定义 repositories-base-packages

不确定如何声明多个基础包,我的 SpEL 知识很原始,所以不确定它是否可能。

【讨论】:

感谢您的回答,但它根本没有解决我们的问题。您的配置将包设置为查找带有 JPA 注释的类,但我们的问题依赖于查找 Spring Data JPA 存储库,这并不相同。此外,我正在寻找一种不需要执行任何进一步配置的解决方案,无论是配置类还是属性。否则我们当前的配置类就足够简单了。 对不起,我误解了这个问题。我已经用另一种解决方案更新了答案。这可行,但不确定是否可以声明多个基础包,具有更多 SpEL 的人将不得不发表评论 再次感谢,但我们正在寻找一种不需要进一步配置,甚至不需要配置属性的解决方案。我们想设置存储库基类并保持默认的自动配置,如 spring boot starter 为 spring data jpa 提供的那样,或者至少提供相同的自动配置级别。

以上是关于有没有办法使用 Spring Boot 自动配置注册存储库基类?的主要内容,如果未能解决你的问题,请参考以下文章

Intellij IDEA 使用Spring-boot-devTools无效解决办法

Intellij IDEA 使用Spring-boot-devTools无效解决办法

有没有办法在 Spring Boot 应用程序配置中使用 Spring Cloud cipher?

Axon Framework - Spring Boot 集成

[Shiro]Shiro整合Spring Boot 自动化配置

有没有办法在 Spring Boot 中获取所有配置属性的名称?