1

我正在 spring data mongodb 中启动一个多租户项目。阅读这篇文章后,按租户收集是 mongodb 中相当不错的方法。

那么如何在 Spring Data Mongo 中实现这一点呢?显然,没有提供开箱即用的解决方案,但我认为我可以通过覆盖确定CollectionName 方法来调整 MongoTemplate,但我认为它不是公共或受保护的方法。

但是,我通过扩展 SimpleMongoDbFactory 并按照此处提供的提示使用 LocalThread 变量,非常容易地为每个租户设置数据库。

所以,问题是:

  1. 有什么安全的方法可以覆盖集合和域类名映射吗?ps:这应该在运行时发生,所以我认为@collection 注释根本没有帮助。
  2. 如果无法按租户收集,那么采用多数据库方法会导致多少性能和资源损失?
4

1 回答 1

0

您可以扩展 MappingMongoEntityInformation 以覆盖 getCollectionName()。存储库操作对每个操作调用 getCollectionName()。我假设tenantId 将是一个 ThreadLocal

public class TenantThreadLocal extends ThreadLocal<String> {
    private final static TenantThreadLocal instance = new TenantThreadLocal();

    public static TenantThreadLocal instance() {
        return instance;
    }
}

并且省略了构造函数的重写类。

public class TenantMappingMongoEntityInformation<T, ID extends java.io.Serializable>  extends MappingMongoEntityInformation<T, ID> {

    @Override
    public String getCollectionName() {
        return TenantThreadLocal.instance().get() + super.getCollectionName();
    }
}

然后创建您的存储库:

MongoPersistentEntity<YourObject> persistentEntity = 
    (MongoPersistentEntity<YourObject>) 
    mongoOperations.getConverter()
    .getMappingContext()
    .getPersistentEntity(YourObject.class);

MongoEntityInformation<YourObject, ObjectId> mongoEntityInformation =
    new MappingMongoEntityInformation<YourObject, ObjectId>(persistentEntity);

CrudRepository<YourObject, ObjectId> repository =
    new SimpleMongoRepository<YourObject, ObjectId>(mongoEntityInformation, mongoOperations);
于 2013-07-28T04:37:49.690 回答