Giriş
Bu yöntem JPA sağlayıcısı olarak Hibernate kullanıyorsak işe yarar.
Kısaca
Hibernate tarafından sağlanan AbstractMultiTenantConnectionProvider sınıfından kalıtan yeni bir ConnectionProvider yazılır. Bu sınıf belirtilen schema'ya geçiş yapar. Bu sınıfı kodlarken şu metodlar override edilir
protected ConnectionProvider getAnyConnectionProvider();public Connection getConnection(String tenantIdentifier);protected ConnectionProvider selectConnectionProvider(String tenantIdentifier);
AbstractMultiTenantConnectionProvider Sınıfı
Örnek
Şöyle yaparız
apublic class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider { private static final String HIBERNATE_PROPERTIES_PATH = "/application.properties"; private final Map<String, ConnectionProvider> connectionProviderMap; public SchemaMultiTenantConnectionProvider() { this.connectionProviderMap = new HashMap<String, ConnectionProvider>(); } @Override public Connection getConnection(String tenantIdentifier) throws SQLException { Connection connection = super.getConnection(tenantIdentifier); connection.createStatement().execute( String.format("SET SCHEMA '%s';", tenantIdentifier)); return connection; } @Override protected ConnectionProvider getAnyConnectionProvider() { return getConnectionProvider(TenantContext.DEFAULT_TENANT_ID); } @Override protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) { return getConnectionProvider(tenantIdentifier); } private ConnectionProvider getConnectionProvider(String tenantIdentifier) { return Optional.ofNullable(tenantIdentifier) .map(connectionProviderMap::get) .orElseGet(() -> createNewConnectionProvider(tenantIdentifier)); } private ConnectionProvider createNewConnectionProvider(String tenantIdentifier) { return Optional.ofNullable(tenantIdentifier) .map(this::createConnectionProvider) .map(connectionProvider -> { connectionProviderMap.put(tenantIdentifier, connectionProvider); return connectionProvider; }) .orElseThrow(() -> new ConnectionProviderException( String.format("Cannot create new connection provider for tenant: %s", tenantIdentifier))); } private ConnectionProvider createConnectionProvider(String tenantIdentifier) { return Optional.ofNullable(tenantIdentifier) .map(this::getHibernatePropertiesForTenantId) .map(this::initConnectionProvider) .orElse(null); } private Properties getHibernatePropertiesForTenantId(String tenantId) { try { Properties properties = new Properties(); properties.load(getClass().getResourceAsStream(HIBERNATE_PROPERTIES_PATH)); return properties; } catch (IOException e) { throw new RuntimeException( String.format("Cannot open hibernate properties: %s)", HIBERNATE_PROPERTIES_PATH)); } } private ConnectionProvider initConnectionProvider(Properties hibernateProperties) { DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl(); connectionProvider.configure(hibernateProperties); return connectionProvider; } }
In this case, we have one method to overload: getConnection(). We call an SQL that changes the schema on the connection we’ve already created. In this implementation, we assumed that the tenantId is also the name of the schema. With tenantId mapping, the name of the schema can also be implemented from this side.
Hiç yorum yok:
Yorum Gönder