2016-06-04 7 views
2

Ich habe versucht, meine JHipster-generierte Anwendung in eine Multi-Tenancy-App mit diesem - http://jannatconsulting.com/blog/?p=41 Blog-Post als Basis zu verwandeln.Jhipster Multi-Mietvertrag mit Hibernate Second Level Caching

Ich habe ein Problem mit Second-Level-Caching aufgetreten. Federverschluß erscheint richtig zu erkennen und zu konfigurieren:

DatabaseConfiguration.java

@Configuration 
@EnableConfigurationProperties(JpaProperties.class) 
@EnableJpaRepositories(
     entityManagerFactoryRef = "masterEntityManager", 
     transactionManagerRef = "masterTransactionManager", 
     basePackages = {"com.quadrimular.nts.helium.repository.master"}) 
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") 
@EnableTransactionManagement 
@EnableElasticsearchRepositories("com.quadrimular.nts.helium.repository.search") 
public class DatabaseConfiguration { 

    @Inject 
    private Environment env; 

    @Autowired(required = false) 
    private MetricRegistry metricRegistry; 

    @Inject 
    private DataSourceProperties datasourceProperties; 

    @Inject 
    private JHipsterProperties jhipsterProperties; 

    @Inject 
    private JpaProperties jpaProperties; 

    @Inject 
    private DataSource dataSource; 

    @Bean(destroyMethod = "close") 
    @ConditionalOnExpression("#{!environment.acceptsProfiles('cloud') && !environment.acceptsProfiles('heroku')}") 
    public DataSource dataSource(DataSourceProperties dataSourceProperties, JHipsterProperties jHipsterProperties) { 
     log.debug("Configuring Master Datasource"); 
     if (dataSourceProperties.getUrl() == null) { 
      log.error("Your database connection pool configuration is incorrect! The application" + 
        " cannot start. Please check your Spring profile, current profiles are: {}", 
       Arrays.toString(env.getActiveProfiles())); 

      throw new ApplicationContextException("Database connection pool is not configured correctly"); 
     } 
     HikariConfig config = new HikariConfig(); 
     config.setDataSourceClassName(dataSourceProperties.getDriverClassName()); 
     config.addDataSourceProperty("url", dataSourceProperties.getUrl()); 
     if (dataSourceProperties.getUsername() != null) { 
      config.addDataSourceProperty("user", dataSourceProperties.getUsername()); 
     } else { 
      config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user 
     } 
     if (dataSourceProperties.getPassword() != null) { 
      config.addDataSourceProperty("password", dataSourceProperties.getPassword()); 
     } else { 
      config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password 
     } 

     //MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration 
     if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) { 
      config.addDataSourceProperty("cachePrepStmts", jHipsterProperties.getDatasource().isCachePrepStmts()); 
      config.addDataSourceProperty("prepStmtCacheSize", jHipsterProperties.getDatasource().getPrepStmtCacheSize()); 
      config.addDataSourceProperty("prepStmtCacheSqlLimit", jHipsterProperties.getDatasource().getPrepStmtCacheSqlLimit()); 
     } 
     if (metricRegistry != null) { 
      config.setMetricRegistry(metricRegistry); 
     } 
     return new HikariDataSource(config); 
    } 

    @Bean(name = "masterEntityManager") 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource(datasourceProperties, jhipsterProperties)); 
     em.setPackagesToScan(new String[]{"com.quadrimular.nts.helium.domain.master"}); 
     em.setJpaVendorAdapter(vendorAdapter); 
     em.setJpaProperties(additionalJpaProperties()); 

     em.setPersistenceUnitName("master"); 

     return em; 
    } 

    private Properties additionalJpaProperties() { 
     Properties properties = new Properties(); 
     for (Map.Entry<String, String> entry : jpaProperties.getHibernateProperties(dataSource).entrySet()) { 
      properties.setProperty(entry.getKey(), entry.getValue()); 
     } 
     return properties; 
    } 
    @Bean(name = "masterTransactionManager") 
    public JpaTransactionManager transactionManager(EntityManagerFactory masterEntityManager){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(masterEntityManager); 
     return transactionManager; 
    } 
} 

Wenn der Frühling zu konfigurieren versucht:

MultiTenancyJPAConfiguration.java

@Configuration 
@EnableConfigurationProperties(JpaProperties.class) 
@EnableJpaRepositories(
     entityManagerFactoryRef = "tenantEntityManager", 
     transactionManagerRef = "tenantTransactionManager", 
     basePackages = {"com.quadrimular.nts.helium.repository.tenant"}) 
@EnableTransactionManagement 
public class MultiTenancyJpaConfiguration { 

    @Bean(name = "tenantEntityManager") 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, 
                  MultiTenantConnectionProvider connectionProvider, 
                  CurrentTenantIdentifierResolver tenantResolver) { 
     LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean(); 
     emfBean.setDataSource(dataSource); 
     emfBean.setPackagesToScan("com.quadrimular.nts.helium.domain.tenant"); 
     emfBean.setJpaVendorAdapter(jpaVendorAdapter()); 

     Map<String, Object> properties = new HashMap<>(); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver); 
     properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy"); 

     emfBean.setJpaPropertyMap(properties); 

     return emfBean; 
    } 

    @Bean(name = "tenantTransactionManager") 
    public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(tenantEntityManager); 
     return transactionManager; 
    } 
} 

Ich bekomme in meinem Spur:

Caused by: org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath. 

Ich habe alle erforderlichen Eigenschaften in meiner Anwendung-dev.yml definiert

hibernate.cache.use_second_level_cache: true 
hibernate.cache.use_query_cache: false 
hibernate.generate_statistics: true 
hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory 

Es scheint, dass es gelesen und von Spring Boot für meine DatabaseConfiguration.java richtig verwendet. Ich kann nicht herausfinden, warum die Eigenschaftendatei nicht gefunden wird. Wenn ich versuche, den Cache zu deaktivieren, indem Sie:

hibernate.cache.use_second_level_cache: false 

DatabaseConfiguration.java erkennt und sich entsprechend verhält jedoch MultiTenancyJPAConfiguration.java wirft immer noch die gleiche Ausnahme.

Fehle ich etwas offensichtlich?

+0

Könnte klingen dumm, aber wie ich sehe, Sie versucht mit dev-Profil, haben Sie versucht, mit prod Profil? Einige Klassen haben bedingte Anmerkungen basierend auf dem Profil. –

+0

@ Gaël Hatte bereits versucht, so schnell Profil zu laufen, um den Cache ohne Glück zu deaktivieren. Habe gerade versucht, mit dem prod-Profil zu laufen, bekomme immer noch genau die selbe Ausnahme. –

Antwort

0

Die Antwort besteht darin, die Werte der jpa-Eigenschaft im Entity Manager zu setzen. Ich bin mir nicht sicher, wie ich das übersehen habe; Ich dachte, dass sie irgendwie schon eingestellt waren.

Zuerst habe ich die Hauptdatenquelle und das von Spring Boot zur Verfügung gestellte jpa-Eigenschaft-Objekt injiziert, wenn ich mich nicht irre.

MultiTenancyJPAConfiguration.java

@Inject 
private JpaProperties jpaProperties; 

@Inject 
private DataSource dataSource; 

I setzen dann die Werte der gleichen Methode in verwendet unter Verwendung DatabaseConfiguration.java

MultiTenancyJPAConfiguration.java

012.
@Bean(name = "tenantEntityManager") 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, 
                  MultiTenantConnectionProvider connectionProvider, 
                  CurrentTenantIdentifierResolver tenantResolver) { 
     LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean(); 
     emfBean.setDataSource(dataSource); 
     emfBean.setPackagesToScan("com.quadrimular.nts.helium.domain.tenant"); 
     emfBean.setJpaVendorAdapter(jpaVendorAdapter()); 

     Map<String, Object> properties = new HashMap<>(); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver); 
     properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy"); 

     emfBean.setJpaPropertyMap(properties); 

     emfBean.setJpaProperties(additionalJpaProperties()); 

     return emfBean; 
    } 

    private Properties additionalJpaProperties() { 
     Properties properties = new Properties(); 
     for (Map.Entry<String, String> entry : jpaProperties.getHibernateProperties(dataSource).entrySet()) { 
      properties.setProperty(entry.getKey(), entry.getValue()); 
     } 
     return properties; 
    } 

Unter Verwendung der Methode additionalJpaProperties() alle Hibernate JPA Eigenschaften für meine Hauptdatenquelle zu erhalten. Ich habe dann die Eigenschaften der Hibernate-Eigenschaft nach den hartcodierten Eigenschaften festgelegt. Klar nicht die sauberste Lösung Ich plane alle jpa-Werte aus der .yml-Datei zu setzen.

Verwandte Themen