feat(db): add postgres setup and multi-tenant config

This commit is contained in:
DanielS
2026-08-18 23:56:51 +02:00
commit 407d40b2e8
13 changed files with 420 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
package com.caspos.config.tenant;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Component
public class SchemaBasedMultiTenantConnectionProvider implements MultiTenantConnectionProvider<String> {
private final DataSource dataSource;
public SchemaBasedMultiTenantConnectionProvider(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Connection getAnyConnection() throws SQLException {
return dataSource.getConnection();
}
@Override
public void releaseAnyConnection(Connection connection) throws SQLException {
connection.close();
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
connection.setSchema(tenantIdentifier);
return connection;
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
try {
connection.setSchema("public");
} finally {
releaseAnyConnection(connection);
}
}
@Override
public boolean supportsAggressiveRelease() {
return true;
}
@Override
public boolean isUnwrappableAs(Class<?> unwrapType) {
return MultiTenantConnectionProvider.class.isAssignableFrom(unwrapType);
}
@Override
public <T> T unwrap(Class<T> unwrapType) {
if (isUnwrappableAs(unwrapType)) {
return unwrapType.cast(this);
}
throw new IllegalArgumentException("Can't unwrap to " + unwrapType.getName());
}
}

View File

@@ -0,0 +1,25 @@
package com.caspos.config.tenant;
public final class TenantContext {
private static final String DEFAULT_TENANT = "public";
private static final ThreadLocal<String> CURRENT_TENANT = ThreadLocal.withInitial(() -> DEFAULT_TENANT);
private TenantContext() {}
public static String getCurrentTenant() {
return CURRENT_TENANT.get();
}
public static void setCurrentTenant(String tenantSchema) {
if (tenantSchema == null || tenantSchema.isBlank()) {
CURRENT_TENANT.set(DEFAULT_TENANT);
} else {
CURRENT_TENANT.set(tenantSchema);
}
}
public static void clear() {
CURRENT_TENANT.set(DEFAULT_TENANT);
}
}

View File

@@ -0,0 +1,19 @@
package com.caspos.config.tenant;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.springframework.stereotype.Component;
@Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver<String> {
@Override
public String resolveCurrentTenantIdentifier() {
String tenant = TenantContext.getCurrentTenant();
return (tenant != null && !tenant.isBlank()) ? tenant : "public";
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}