发布于 2013-05-02 04:34:03
这里有相当多的方法来剥猫皮。基本上,这一切都归结为您想要应用租户的级别。
基础知识
基本方法是在每个线程的基础上绑定标识客户的某种键,这样您就可以了解当前执行线程所处理的客户的信息。这通常是通过在ThreadLocal中填充一些与身份验证相关的信息来实现的,因为您通常可以从登录的用户派生租户。
现在,如果这一点到位,那么在哪里应用租户知识有几个选择。让我简要地概述一下最常见的几个:
数据库级别的多租户
为多个客户端分离数据的一种方法是为每个租户提供单独的数据库。Spring Data MongoDB的核心抽象是MongoDBFactory接口。这里最简单的方法是覆盖SimpleMongoDbFactory.getDb(String name),并使用数据库名称调用父方法,例如,通过租户前缀等进行丰富。
集合级别的多租户
另一种选择是具有租户特定的集合,例如通过租户前缀或后缀。这种机制实际上可以通过在@Document注释的collectionName属性中使用Spring Expression language (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 (以及相应的存储库抽象)将使用文档类的映射元数据,映射子系统将评估collectionName属性以了解要与之交互的集合。
发布于 2014-06-13 20:42:30
我对奥利弗·吉尔克也有过类似的做法。至少在数据库级别上是这样。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());发布于 2020-09-08 01:17:57
对于springboot 2.3.3
覆盖doGetMongoDatabase有助于实现多租户
protected MongoDatabase doGetMongoDatabase(String dbName) {
}https://github.com/jose-m-thomas/mongo_multi_tenancy_spring_boot_2_3_3
https://stackoverflow.com/questions/16325606
复制相似问题