Multi-tenant mongodb database based with spring data

隐身守侯 提交于 2020-01-06 14:05:21

问题


I would like to make my web application that is using mongodb and spring-data multitenat.

Basically I would like to replicate all my entities(collections) into different databases. Then (based on some rule as for example the user that is logged in the system) I want to store some entity instance (document) into the right database.

For example I have a Service Called DBNameProviderService.getDbName() that dynamically returns me the name of the database. How can I use this service to dynamically select the correct Db?

Edited

Sorry if it is not enough clear. Maybe with an example will be more clear.

In my system I can registe/login users (they are stored stored in the User collection in database named general_db).

I have also an entity A (marked as multitenant simply extending an interface). If I am logged in as User1 I want to store an A instance always in the Database User1_db in the collection A, while if I am logged in as User2 and I want to store an A instance in User2_db in the collection A.

So in this scenario the problem is that I cannot create a mongotemplate bean for each user because users can register in the system, so it is dynamic. I need that the MongoTemplate choose dynamically the database.


回答1:


You should take a look at my github project, I had a very similar problem.

https://github.com/Loki-Afro/multi-tenant-spring-mongodb




回答2:


See same kind of issues Spring-data-mongodb connect to multiple databases in one Mongo instance There is also the possibility of sharding and set as part of the key the id you want to use and search.




回答3:


I too faced similar problem while using spring mongodb as multitenant. Finally i figured out a way by using Adapter to manage the MongoTemplates in a static Collection.

SpringMongoConfigAdapater is a sample snippet which can help the overview.

Spring Config:

<bean id="springConfig"  class="com.company.config.SpringMongoConfigAdapater"  >

<!-- default db initialization -->

    <property name="defaultDBName" value="${MONGOHQ_DB:db}"></property> 

<!-- mongo instance is referred to http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd  -->

     <property name="mongo" ref="mongo"></property>

        </bean>

SpringMongoConfigAdapter:

public class SpringMongoConfigAdapater {
   // Each Tenant is referenced to MongoTemplate
 static HashMap<String, MongoTemplate> templateMap = new HashMap<>();
 // Each Tenant is referenced to GridFS Template
    static  HashMap<String, GridFsTemplate> gridfsMap = new HashMap<>();
    // @Autowired
    Mongo mongo;
    @Autowired
    private MongoConverter mappingMongoConverter;
    public HashMap<String, MongoTemplate> getTemplateMap() {
        return templateMap;
    }
    /**
     * @return the defaultDBName
     */
    public String getDefaultDBName() {
        return defaultDBName;
    }   /**
     * @param defaultDBName the defaultDBName to set
     */
    public void setDefaultDBName(String defaultDBName) {
        this.defaultDBName = defaultDBName;
    }
    String defaultDBName;
    @Produces
    @ApplicationScoped
    public MongoTemplate templateManager() throws Exception {
        String dbName = MyThreadLocal.getDBName();
        if (StringUtils.isBlank(dbName)) {
            dbName = defaultDBName;
        }
        if (templateMap.get(dbName) == null) {
            MongoTemplate template = mongoTemplate(dbName);
            templateMap.put(dbName, template);
        }
        return templateMap.get(dbName);
    }
    //this is for gridfs template.
    public GridFsTemplate gridfsTemplateManager() throws Exception {
        String dbName = MyThreadLocal.getDBName();
        if (StringUtils.isBlank(dbName)) {
            dbName = defaultDBName;
        }
        if (gridfsMap.get(dbName) == null) {
            GridFsTemplate template = new GridFsTemplate(mongoDbFactory(dbName), mappingMongoConverter);
            gridfsMap.put(dbName, template);
        }
        return gridfsMap.get(dbName);
    }
    MongoTemplate mongoTemplate(String name) throws Exception {
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(name));
        return mongoTemplate;
    }
    MongoDbFactory mongoDbFactory(String name) throws Exception {
        return new SimpleMongoDbFactory(mongo, name);
    }
    /**
     * @return the gridfsMap
     */
    public HashMap<String, GridFsTemplate> getGridfsMap() {
        return gridfsMap;
    }
    /**
     * @param gridfsMap the gridfsMap to set
     */
    public void setGridfsMap(HashMap<String, GridFsTemplate> gridfsMap) {
        this.gridfsMap = gridfsMap;
    }
}

Now while calling from your code,

 springMongoConfigAdapater .templateManager().getMongoOps().findAll(User.class); 

On top of it, Use ThreadLocal to initialize the MultiTenant Identifier (which could be dbName) I gave a detailed info which might help you, Click here!



来源:https://stackoverflow.com/questions/20791656/multi-tenant-mongodb-database-based-with-spring-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!