如何实现多租户Spring Boot应用程序(每个用户都有自己的数据库)



我正在构建一个带有弹簧引导的REST-API,我想实现一个多对映结构来处理数据。我想要一个名为Main的数据库,该数据库将具有User表,该表将具有关于用户的数据(用户名、密码…和一个字段database,该字段将表示哪个数据库被指定给该用户(。每次用户注册时,都会创建相应的DB(这是我面临困难的地方之一(。我读过不同的教程,它们都在application.properties文件中有预定义的Datasource。显然,这里的情况并非如此,因为将创建每个用户的DB";在飞行中";,或者如果已经创建则访问。

工作流程如下(解释尽可能简单(:

  1. 用户注册
  2. 应用程序创建用户实体,将其保存到Main数据库中,并为用户创建相应的数据库
  3. 如果用户通过了身份验证,该应用程序会检查每个调用,然后从他的数据库中获取数据

然后,当数据库自动创建时,有很多关于填充数据库的问题。但首先:(

我的堆栈:POSTGRESQL,Spring Boot

提前谢谢。

多租户可以根据需要通过以下步骤实现。

  1. 添加两个配置类,一个用于共享数据库,另一个用于租户数据库,用于配置LocalContainerEntityManagerFactoryBean。此bean应该为LocalContainerEntityManagerFactoryBean设置所需的多租户属性例如
Map<String, Object> properties = hibernateProperties.determineHibernateProperties(
this.properties.getProperties(), new HibernateSettings());

properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, this.connectionProvider);
properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, this.resolver);
properties.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");

这个类还应该为每种类型实现命名的bean transactionManager。例如

@Bean(name = "tenantTransactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(this.entityManagerFactory().getObject());
return tm;
}
  1. 实现接口CurrentTenantIdentifierResolver和方法resolveCurrentTenantIdentity。这应该返回基于当前登录用户的租户的数据库名称。或者默认数据库名称(如果没有用户登录(

  2. 线程安全上下文持有者,用于记住当前租户名称

  3. 使用@Transactional注释为实体类的服务实现进行注释,并传递适当实体管理器的bean名称,例如

@Transactional("tenantTransactionManager") // for tenant database

@Transactional("transactionManager") // for shared database.
  1. 当新用户注册时,设置数据库架构创建方法。并将租户数据库名称维护为共享模式中用户表中的列之一。

  2. 如果您使用的是spring安全性,请实现UserDetailsService接口并实现方法loadUserByUsername,使其返回TenantUser类的对象,该对象包含登录用户的附加信息(租户数据库名称(。

public class TenantUser extends org.springframework.security.core.userdetails.User {

/** The tenand id. */
private String tenantId;

希望这些步骤能帮助你实现你想要的。有许多文章详细解释了所有这些步骤。我的实现深深地嵌入到我的项目中,因此它不处于可以作为工作示例共享的状态。

很乐意回答任何进一步的问题

我在这里找到了问题的完整解决方案:

多租户:使用Spring Data JPA 管理多个数据源

非常感谢作者@Cepr0。

唯一缺少的就是动态创建DB。当我完成我的实现时,我将在这里更新答案。

更新

我用以下代码创建了数据库,这是@Milind Barve推荐的。所以谢谢你。

Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","postgres", "password");
Statement smt = con.createStatement();
smt.executeUpdate("CREATE DATABASE [name_of_db_here] WITH OWNER DEFAULT");

更新:初始化每个新创建的DB的模式,我创建了一个包含所有表创建的.sql文件,并使用FlyWay初始化每个新创建的DB

// INITIALIZE THE DB
Flyway flyway = Flyway.configure()
.dataSource(dataSource)
.target(MigrationVersion.LATEST)
.load();
flyway.migrate();

最新更新