当前位置: 首页 > 知识库问答 >
问题:

基于Spring数据的多租户mongoDB数据库

郏经纬
2023-03-14

我想让我的web应用程序使用mongodb和spring data multitenat。

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

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

编辑

抱歉,如果不够清楚。也许举个例子会更清楚。

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

我还有一个实体A(标记为多租户,只是扩展了一个接口)。如果我以用户1的身份登录,我希望在集合A的数据库User1_db中始终存储一个A实例,而如果我以用户2的身份登录,我希望在集合A的User2_db中存储一个A实例。

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

共有3个答案

潘银龙
2023-03-14

在使用spring mongodb作为多租户时,我也遇到了类似的问题。最后,我找到了一种方法,使用Adapter在静态集合中管理MongoTemplates。

SpringMongoConfigadapter是一个示例片段,可以帮助您进行概述。

Spring配置

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

最重要的是,使用线程本地初始化多租户标识符(可能是dbName)我给了一个详细的信息,这可能会帮助你,点击这里!

邹英光
2023-03-14

查看类似问题Spring data mongodb连接到一个Mongo实例中的多个数据库也有可能进行切分,并将要使用和搜索的id设置为密钥的一部分。

松旻
2023-03-14

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

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

 类似资料:
  • null 如何实现:Spring Data JPA不支持全局筛选器,所以我需要添加定制Spring Data JPA存储库,该存储库可以反过来为基于鉴别器的解决方案应用全局筛选器? 到底有没有可能用Spring Data JPA+Hibernate 3实现我的需求?

  • 我认为为每个租户创建一个Redis实例是一个很好的解决方案。 我有一个包含租户id和Redisendpoint的映射,这是专用于这个租户的。 地图数据如下所示:

  • 是否可以将Spring Boot配置为使用MultiTenantConnectionProvider,以便我的系统的每个客户端都连接到自己的私有数据库? 具体来说,我希望使用内置的hibernate支持多租户: http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#d5e4561 这是我想要的配置的一个例子,但我不知

  • 我们正在开发一个多租户应用程序。在体系结构方面,我们为业务逻辑设计了共享中间层,为数据持久性设计了每个租户一个数据库。也就是说,业务层将与每个租户的数据库服务器建立一组连接(连接池)。这意味着应用程序为每个租户维护单独的连接池。如果我们预计约有5000个租户,那么这个解决方案需要高资源利用率(每个租户的应用服务器和数据库服务器之间的连接),这会导致性能问题。 我们已经通过保持公共连接池解决了这个问

  • Spring data提供了各种用于CRUD、分页和mongob排序的存储库。当我们需要来自mongob的使用各种属性的文档时,我们倾向于编写方法或编写带有显式查询的方法,并用注释。但是如果我的文档有许多属性并且我需要各种获取文档的方法,Spring是否提供了一种“存储库方法”来接收属性和值的Map?编写各种可能很麻烦。使用QueryDSL似乎是一种选择,但需要代码生成和build.gradle更

  • 问题内容: 让我们说我需要设计一个数据库,该数据库将托管多个公司的数据。现在出于安全和管理目的,我需要确保正确隔离了不同公司的数据,但我也不想启动10个mysql进程来在10个不同的服务器上托管10个公司的数据。使用mysql数据库执行此操作的最佳方法是什么。 问题答案: 多租户数据库有几种方法。为了进行讨论,它们通常分为三类。 每个租户一个数据库。 共享数据库,每个租户一个模式。 共享数据库,共