How To Configure MongoDb Collection Name For a Class in Spring Data

后端 未结 5 853
灰色年华
灰色年华 2020-12-08 15:16

I have a collection called Products in my MongoDB database, which is represented by the interface IProductPrice in my Java code. The following repo

相关标签:
5条回答
  • 2020-12-08 15:40

    using answer from Oliver Gierke above, working on a project where I need to create multiple collections for one entity, I wanted to use the spring repositories and needed to specify the entity to use before using the repository.

    I managed to modify the repository collection name on demand using this system, it using SPeL. You can only work on 1 collection at a time though.

    Domain object

    @Document(collection = "#{personRepository.getCollectionName()}")
    public class Person{}
    

    Default Spring Repository:

    public interface PersonRepository 
         extends MongoRepository<Person, String>, PersonRepositoryCustom{
    }
    

    Custom Repository Interface:

    public interface PersonRepositoryCustom {
        String getCollectionName();
    
        void setCollectionName(String collectionName);
    }
    

    implementation:

    public class PersonRepositoryImpl implements PersonRepositoryCustom {
    
        private static String collectionName = "Person";
    
        @Override
        public String getCollectionName() {
            return collectionName;
        }
    
        @Override
        public void setCollectionName(String collectionName) {
            this.collectionName = collectionName;
        }
    }
    

    To use it:

    @Autowired
    PersonRepository personRepository;
    
    public void testRetrievePeopleFrom2SeparateCollectionsWithSpringRepo(){
            List<Person> people = new ArrayList<>();
            personRepository.setCollectionName("collectionA");
            people.addAll(personRepository.findAll());
            personDocumentRepository.setCollectionName("collectionB");
            people.addAll(personRepository.findAll());
            Assert.assertEquals(4, people.size());
    }
    

    Otherwise if you need to use configuration variables, you could maybe use something like this? source

    @Value("#{systemProperties['pop3.port'] ?: 25}") 
    
    0 讨论(0)
  • 2020-12-08 15:40

    I use static class and method in SpEL;

    public class CollectionNameHolder {
        private static final ThreadLocal<String> collectionNameThreadLocal = new ThreadLocal<>();
    
        public static String get(){
            String collectionName = collectionNameThreadLocal.get();
            if(collectionName == null){
                collectionName = DataCenterApiConstant.APP_WECHAT_DOCTOR_PATIENT_COLLECTION_NAME;
                collectionNameThreadLocal.set(collectionName);
            }
            return collectionName;
        }
    
        public static void set(String collectionName){
            collectionNameThreadLocal.set(collectionName);
        }
    
        public static void reset(){
            collectionNameThreadLocal.remove();
        }
    }
    

    In Entity class ,@Document(collection = "#{T(com.test.data.CollectionNameHolder).get()}")

    And then ,use

    CollectionNameHolder.set("testx_"+pageNum) 
    

    in Service , and

    CollectionNameHolder.reset();
    

    Hope it helps you.

    0 讨论(0)
  • 2020-12-08 15:42

    The only way you can currently achieve this is by annotating your domain class with @Document using the collection property to define the name of the collection instances of this class shall be persisted to.

    However, there's a JIRA issue open that suggests adding a pluggable naming strategy to configure the ways class, collection and property names are handled in a more global way. Feel free to comment your use case and vote it up.

    0 讨论(0)
  • 2020-12-08 15:51

    A little late, but I've found you can set the mongo collection name dynamically in spring-boot accessing the application configuration directly.

    @Document(collection = "#{@environment.getProperty('configuration.property.key')}")
    public class DomainModel {...}
    

    I suspect you can set any annotation attribute this way.

    0 讨论(0)
  • 2020-12-08 15:57

    The only comment I can add is that you have to add @ prefix to the bean name:

    collection = "#{@beanName.method()}"
    

    for the bean factory to inject the bean:

    @Document(collection = "#{@configRepositoryCustom.getCollectionName()}")
    public class Config {
    
    }
    

    I struggled to figure it out..

    COMPLETE EXAMPLE:

    @Document(collection = "#{@configRepositoryCustom.getCollectionName()}")
    public class Config implements Serializable {
     @Id
     private String uuid;
     private String profile;
     private String domain;
     private String label;
     private Map<String, Object> data;
     // get/set
    }
    
     public interface ConfigRepositoryCustom {
       String getCollectionName();
       void setCollectionName(String collectionName);
     }
    
    @Component("configRepositoryCustom")
    public class ConfigRepositoryCustomImpl implements ConfigRepositoryCustom {
     private static String collectionName = "config";
     @Override
     public String getCollectionName() {
      return collectionName;
     }
     @Override
     public void setCollectionName(String collectionName) {
     this.collectionName = collectionName;
     }
    }
    
    @Repository("configurations")
    public interface ConfigurationRepository extends MongoRepository<Config, String>, ConfigRepositoryCustom {
      public Optional<Config> findOneByUuid(String Uuid);
      public Optional<Config> findOneByProfileAndDomain(String profile, String domain);
    }
    

    usage in serviceImpl:

    @Service
    public class ConfigrationServiceImpl implements ConfigrationService {
     @Autowired
     private ConfigRepositoryCustom configRepositoryCustom;
    
     @Override
     public Config create(Config configuration) {
       configRepositoryCustom.setCollectionName( configuration.getDomain() ); // set the collection name that comes in my example in class member 'domain'
       Config configDB = configurationRepository.save(configuration);
       return configDB;
    }
    
    0 讨论(0)
提交回复
热议问题