Dynamically generating Spring Data Repositories

2k Views Asked by At

I am working on creating a library built on top of spring-data so that it would be able to dynamically generate Spring Data repositories. I was hoping to create a generic wrapper of this process that operates on the Spring Data abstraction.

This way depending on what dependency is added to the classpath example: spring-data-jpa or spring-data-mongodb I would be able to generate repositories and inject them into my spring context.

I was having trouble finding good documentation on how to go about doing this. Any ideas?

1

There are 1 best solutions below

2
On BEST ANSWER

Spring provides a @Conditional annotation for controlling which beans/configurations are picked up depending on classpath ( similar with the spring-boot autoconfiguration ).

You could define two configuration classes which are picked up by spring based on your classpath. For example:

  1. Configuration for JPA present on classpath could look something like.

    @Configuration
    @EnableJpaRepositories(basePackages=...)
    @Conditional(JpaClassPathCondition.class)
    public class JpaAutoConfiguration {
    
        static class JpaClassPathCondition implements Condition {
    
            @Override
            public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                return ClassUtils.isPresent("javax.persistence.EntityManager", JpaAutoConfiguration.class.getClassLoader());
            }
         }
    }
    
  2. Configuration for MongoDB:

    @Configuration
    @EnableMongoRepositories(...)
    @Conditional(MongoClassPathCondition.class)
    public class MongoAutoConfiguration {
    
        static class MongoClassPathCondition implements Condition {
    
            @Override
            public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                return !ClassUtils.isPresent("javax.persistence.EntityManager", MongoAutoConfiguration.class.getClassLoader()); )//or whatever classpath element fits you best
    
            }
         }
    }
    

All you need to do from this point forward is to use both configuration classes in your module and let spring do it's magic