制作spring-data-mongodb多租户
在最后一个八月sbzoom的post中提出了一个使spring-data-mongoDB多租户的解决方案:
“你必须创建自己的RepositoryFactoryBean。这是Spring Data MongoDB参考文档中的示例。你仍然需要实现自己的MongoTemplate并延迟或删除ensureIndexes()调用。但是你必须重写几个类来确保调用你的MongoTemplate而不是Spring。“
有没有人实现这个或类似的东西?
有很多方法可以让猫在这里去皮。 它基本上归结为您希望应用租赁的级别。
基本
基本方法是在每个线程的基础上绑定某种识别客户的密钥,以便您可以了解当前执行线程处理的客户。 这通常通过使用一些身份validation相关信息填充ThreadLocal
来实现,因为您通常可以从登录用户派生租户。
现在,如果有的话,有几个选项可以应用租户知识。 让我简要概述最常见的一些:
数据库级别的多租户
为多个客户端分隔数据的一种方法是为每个租户分配单独的数据库。 Spring Data MongoDB的核心抽象是MongoDBFactory
接口。 这里最简单的方法是覆盖SimpleMongoDbFactory.getDb(String name)
并使用数据库名称调用父方法,例如通过租户前缀等进行丰富。
收集级别的多租户
另一种选择是租户特定的集合,例如通过租户预先或后缀。 实际上可以通过在@Document
注释的collectionName
属性中使用Spring Expression语言(SpEl)来利用此机制。 首先,通过Spring bean公开租户前缀:
@Component("tenantProvider") public class TenantProvider { public String getTenantId() { // … implement ThreadLocal lookup here } }
然后在您的域类型@Document
映射中使用SpEL:
@Document(collectionName = "#{tenantProvider.getTenantId()}_accounts" public class Account { … }
SpEl允许您按名称引用Spring bean并对它们执行方法。 MongoTemplate
(以及MongoTemplate
的存储库抽象)将使用文档类的映射元数据,映射子系统将评估collectionName
属性以找出要与之交互的集合。
我和Oliver Gierke有类似的方法。 至少在数据库级别上。 https://github.com/Loki-Afro/multi-tenant-spring-mongodb您应该能够做到这样的事情:
MultiTenantMongoDbFactory.setDatabaseNameForCurrentThread("test"); this.personRepository.save(createPerson("Phillip", "Wirth", ChronoUnit.YEARS.between( LocalDate.of(1992, Month.FEBRUARY, 3), LocalDate.now()))); System.out.println("data from test: " + this.personRepository.findAll()); // okay? fine. - lets switch the database MultiTenantMongoDbFactory.setDatabaseNameForCurrentThread("test666"); // should be empty System.out.println("data from test666: " + this.personRepository.findAll());