2014-11-12 17 views
9

È possibile configurare Spring Boot per utilizzare un MultiTenantConnectionProvider in modo che ciascun client del sistema si connetta al proprio database privato?Spring Boot + Spring Data con multi tenancy

In particolare sto cercando di utilizzare il supporto per sospensione built-in per il multi-tenancy:

E questo è un esempio del tipo di configurazione sono dopo, ma io non riesco a capire come utilizzare questo in una configurazione di avvio primavera:

Ho provato ad aggiungere queste proprietà per application.properties:

spring.jpa.hibernate.multiTenancy=DATABASE 
spring.jpa.hibernate.tenant_identifier_resolver=com.mystuff.MyCurrentTenantIdentifierResolver 
spring.jpa.hibernate.multi_tenant_connection_provider=com.mystuff.MyMultiTenantConnectionProviderImplX 

Ho anche provato codificare fino mia CurrentTenantIdentifierResolver e MultiTenantConnectionProvider e ho cercato di servire questi dal mio principale @Configuration di fagioli:

@Bean 
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() { 
    return new CurrentTenantIdentifierResolver() { 
     public String resolveCurrentTenantIdentifier() { 
      // this is never called ... 
     } 
     public boolean validateExistingCurrentSessions() { 
      // this is never called ... 
     } 
    }; 
} 

@Bean 
public MultiTenantConnectionProvider multiTenantConnectionProvider() { 
    return new AbstractMultiTenantConnectionProvider() { 
     protected ConnectionProvider getAnyConnectionProvider() { 
      // this is never called ... 
     } 
     protected ConnectionProvider selectConnectionProvider(String s) { 
      // this is never called ... 
     } 
    }; 
} 

Nessuno di questi sembra avere alcun effetto quindi la mia domanda è davvero come ottenere i dati spring-boot/spring per utilizzare queste classi multi-tenant?

Grazie per il vostro aiuto!

+0

Vedere la mia domanda [qui] (https://stackoverflow.com/questions/44366221/hibernate-multitenancy-with-spring-jpa).
Uso un 'LocalContainerEntityManagerFactoryBean' e funziona.
Ma non capisco completamente la differenza tra questo e '.yml'or'.properties'.
Sono d'accordo con @ M.Deinum, in 'yml' hibernate controlla il ciclo di vita di' mulitTenantConnectionProvider' e 'CurrentTenantIdentifierResolver'. Ma non so perché. – linghu

risposta

6

Any property per JPA/Hibernate non definito può essere impostato utilizzando la proprietà spring.jpa.properties in application.properties.

Il campione si collega a ha 3 proprietà per multi-tenancy:

<prop key="hibernate.multiTenancy">SCHEMA</prop> 
<prop key="hibernate.tenant_identifier_resolver">com.webapp.persistence.utility.CurrentTenantContextIdentifierResolver</prop> 
<prop key="hibernate.multi_tenant_connection_provider">com.webapp.persistence.utility.MultiTenantContextConnectionProvider</prop> 

Che convertito in primavera avvio sarebbero le seguenti proprietà nel file application.properties.

spring.jpa.properties.hibernate.multiTenancy=SCHEMA 
spring.jpa.properties.hibernate.tenant_identifier_resolver=com.mystuff.MyCurrentTenantIdentifierResolver 
spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.webapp.persistence.utility.MultiTenantContextConnectionProvider 

Per la situazione (come indicato nella domanda).

spring.jpa.properties.hibernate.multiTenancy=DATABASE 
spring.jpa.properties.hibernate.tenant_identifier_resolver=com.webapp.persistence.utility.CurrentTenantContextIdentifierResolver 
spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.mystuff.MyMultiTenantConnectionProviderImplX 

Non funzionerà con i bean Spring manged poiché Hibernate controlla il ciclo di vita di tali istanze.

Per ulteriori proprietà vedere lo stivale reference guide.

+0

Grazie, ho perso il ".properties". un po '(il docco è chiaro col senno di poi, ma mi è mancato le prime volte che l'ho letto). Un po 'una sfida ora intorno al ciclo di vita come hai evidenziato. In particolare ottenere l'accesso ad altri servizi Spring da ConnectionProvider. Ho provato l'approccio di mantenere un riferimento statico al servizio di cui ho bisogno ma il materiale di ibernazione viene creato per primo, quindi è nullo quando ne ho bisogno. Fallback non utilizza i servizi Spring in queste classi ma rende il codice disordinato. Se hai qualche idea su questo lato, mi piacerebbe ascoltarli. – zonski

+1

Anche se un po 'hacky potresti usare 'ContextLoader.getCurrentWebApplicationContext' per accedere al contesto e fare le ricerche. O creare una classe di supporto che è possibile utilizzare per recuperare i servizi. –

+1

Sì, grazie - Ho provato entrambi, ma qualunque cosa stia facendo Spring Boot fa sì che MultiTenantConnectionProvider venga istanziato prima che esista il contesto, quindi ContextLoader. getCurrentWebApplicationContext() è null quando viene chiamato per la prima volta getAnyConnectionProvider() e le classi helper non riescono a trovare i servizi neanche a questo punto. Penso di non essere in grado di utilizzare i servizi Spring all'interno di MultiTenantConnectionProvider. Peccato, ma non la fine del mondo. Grazie mille per il vostro aiuto, lo apprezzo davvero! – zonski