基于弹簧数据的多租户mongodb数据库

时间:2013-12-26 21:44:13

标签: spring mongodb spring-data-mongodb

我想创建使用mongodb和spring-data multitenat的web应用程序。

基本上我想将我的所有实体(集合)复制到不同的数据库中。然后(基于一些规则,例如登录系统的用户)我想将一些实体实例(文档)存储到正确的数据库中。

例如,我有一个服务调用DBNameProviderService.getDbName(),它动态地返回数据库的名称。如何使用此服务动态选择正确的Db?

被修改

对不起,如果还不够清楚的话。也许用一个例子会更清楚。

在我的系统中,我可以注册/登录用户(它们存储在名为general_db的数据库中的User集合中。)

我还有一个实体A(标记为多租户只是扩展一个接口)。如果我以User1身份登录,我想将A实例始终存储在集合A中的Database User1_db中,而如果我以User2身份登录,并且我想将A实例存储在集合A中的User2_db中。

所以在这种情况下,问题是我无法为每个用户创建一个mongotemplate bean,因为用户可以在系统中注册,因此它是动态的。我需要MongoTemplate动态选择数据库。

4 个答案:

答案 0 :(得分:1)

你应该看看我的github项目,我有一个非常类似的问题。

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

答案 1 :(得分:0)

查看同类问题Spring-data-mongodb connect to multiple databases in one Mongo instance 还可以进行分片并将其设置为要使用和搜索的ID的一部分。

答案 2 :(得分:0)

使用spring mongodb作为多租户时,我也遇到了类似的问题。最后,我想通过使用Adapter来管理静态Collection中的MongoTemplates。

SpringMongoConfigAdapater是一个示例代码段,可以帮助您进行概述。

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;
    }
}

现在从您的代码调用时,

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

在它之上,使用ThreadLocal初始化MultiTenant标识符(可能是dbName) 我给出了一个可能对你有帮助的详细信息, 点击here

答案 3 :(得分:0)

请参考springboot 2.3.3

https://github.com/jose-m-thomas/mongo_multi_tenancy_spring_boot_2_3_3

重载doGetMongoDatabase有助于实现多租户

df.plot(kind='bar',figsize=(50,40))
plt.grid(which='major', linestyle='-', linewidth='0.5', color='green')
plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black')
plt.show()