我正在使用弹簧应用程序(使用弹簧靴),直到今天早上才能正常工作。我现在需要配置第二个数据源以使用两个不同的数据库(mysql + embedded h2)。
我现在有两个班级" MainDatabaseConfiguration"和" EmbeddedDatabaseConfiguration",它们都提供类型为Bean的数据" DataSource" (mainDataSource和embeddedDataSource),以及类型为" EntityManager"," EntityManagerFactory"的关联Bean。和" TransactionManager"。
不幸的是,应用程序初始化失败并出现以下错误:
...
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.
at org.hibernate.cache.internal.NoCachingRegionFactory.buildEntityRegion(NoCachingRegionFactory.java:83)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:363)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857)
...
然而,当我查看我的配置文件时:
application-dev.yml:
server:
port: 8080
address: localhost
spring:
profiles: dev
datasource:
main:
dataSourceClassName: org.h2.jdbcx.JdbcDataSource
url: jdbc:h2:mem:jhipster
databaseName:
serverName:
username:
password:
embedded:
dataSourceClassName: org.h2.jdbcx.JdbcDataSource
url: jdbc:h2:mem:jhipster
databaseName:
serverName:
username:
password:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
database: H2
openInView: false
show_sql: true
generate-ddl: false
hibernate:
ddl-auto: none
naming-strategy: org.hibernate.cfg.EJB3NamingStrategy
properties:
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
thymeleaf:
mode: XHTML
cache: false
metrics:
jmx.enabled: true
graphite:
enabled: false
host:
port:
cache:
timeToLiveSeconds: 3600
ehcache:
maxBytesLocalHeap: 16M
# You can add as many as folders to watch
# You just need to add a dash + the directory to watch
hotReload:
enabled: true
package:
project: com.sfr.sio
domain: com.sfr.sio.domain
restdto: com.sfr.sio.web.rest.dto
liquibase:
defaultCatalogName:
defaultSchema: public
watchdir:
- target/classes
属性&#34; hibernate.cache.region.factory_class&#34;存在。我对第二个数据源的文件所做的唯一改变是在&#34; spring.datasource&#34;将它分成两部分(spring.datasource.main和spring.datasource.embedded)。 (注意:在我的开发环境中,两个数据源都是H2,但在生产中使用了mysql) 正如您所看到的,错误中提到的属性存在,但Spring似乎无法检索它。
可能涉及错误的其他类的代码:
mainDataSourceConfiguration.java:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "mainEntityManagerFactory",
transactionManagerRef = "mainTransactionManager",
basePackages = { "com.sfr.sio.repository" })
public class MainDatabaseConfiguration extends AbstractDatabaseConfiguration implements EnvironmentAware {
/** prefix for the main datasource properties. **/
private static final String MAIN_DATASOURCE_PREFIX = "spring.datasource.main.";
/** Logger. */
private final Logger log = LoggerFactory.getLogger(MainDatabaseConfiguration.class);
@Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, MAIN_DATASOURCE_PREFIX);
}
/**
* Main Datasource bean creator.
* <ul>
* <li>Mysql for qualif and sfr environments</li>
* <li>h2 for dev environment</li>
* </ul>
*
* @return the datasource.
*/
@Bean(name="mainDataSource")
@Primary
public DataSource dataSource() {
log.debug("Configuring Datasource");
if (propertyResolver.getProperty(URL_PARAMETER) == null && propertyResolver.getProperty(DATABASE_NAME_PARAMETER) == 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(propertyResolver.getProperty(DS_CLASS_NAME_PARAMETER));
if (propertyResolver.getProperty(URL_PARAMETER) == null || "".equals(propertyResolver.getProperty(URL_PARAMETER))) {
config.addDataSourceProperty(DATABASE_NAME_PARAMETER, propertyResolver.getProperty(DATABASE_NAME_PARAMETER));
config.addDataSourceProperty(SERVER_NAME_PARAMETER, propertyResolver.getProperty(SERVER_NAME_PARAMETER));
} else {
config.addDataSourceProperty(URL_PARAMETER, propertyResolver.getProperty(URL_PARAMETER));
}
config.addDataSourceProperty(USER_PARAM, propertyResolver.getProperty(USERNAME_PARAMETER));
config.addDataSourceProperty(PASSWORD_PARAMETER, propertyResolver.getProperty(PASSWORD_PARAMETER));
return new HikariDataSource(config);
}
/**
* @return the entity manager for the main datasource
* @see MainDatabaseConfiguration.dataSource()
*/
@Bean(name = "mainEntityManager")
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
/**
* @return the entity manager factory for the main datasource
* @see MainDatabaseConfiguration.dataSource()
*/
@Bean(name = "mainEntityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(this.dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.sfr.sio.domain");
lef.setPersistenceUnitName("mainPersistenceUnit");
lef.afterPropertiesSet();
return lef.getObject();
}
/**
* @return the transaction manager for the main datasource
* @see MainDatabaseConfiguration.dataSource()
*/
@Bean(name = "mainTransactionManager")
@Primary
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
/**
* Liquibase bean creator.
* @return the liquibase bean
*/
@Bean
@Profile(value = Constants.SPRING_PROFILE_DEVELOPMENT)
public SpringLiquibase liquibase() {
log.debug("Configuring Liquibase");
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource());
liquibase.setChangeLog("classpath:config/liquibase/master.xml");
liquibase.setContexts("development, production");
return liquibase;
}
}
MainDatabaseConfiguration和EmbeddedDatabaseConfiguration之间的唯一区别是embeddedDatasource替换了mainDatasource。代码是相同的。
CacheConfiguration.java
@Configuration
@EnableCaching
@AutoConfigureAfter(value = {MetricsConfiguration.class, MainDatabaseConfiguration.class, EmbeddedDatabaseConfiguration.class})
public class CacheConfiguration {
/** Logger. */
private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
/** Entity manager. */
@PersistenceContext(unitName="mainPersistenceUnit")
private EntityManager mainEntityManager;
/** Current environment. */
@Inject
private Environment env;
/** Metrics regitry. */
@Inject
private MetricRegistry metricRegistry;
/** Ehcache manager. */
private net.sf.ehcache.CacheManager cacheManager;
/** TTL parameter. */
private static final Integer CACHE_TIME_TO_LIVE = 3600;
/**
* Prepare destroy of the object.
*/
@PreDestroy
public void destroy() {
log.info("Remove Cache Manager metrics");
SortedSet<String> names = metricRegistry.getNames();
for (String name : names) {
metricRegistry.remove(name);
}
log.info("Closing Cache Manager");
cacheManager.shutdown();
}
/**
* Cache manager bean creator.
* @return the cache manager.
*/
@Bean
public CacheManager cacheManager() {
log.debug("Starting Ehcache");
cacheManager = net.sf.ehcache.CacheManager.create();
cacheManager.getConfiguration().setMaxBytesLocalHeap(env.getProperty("cache.ehcache.maxBytesLocalHeap", String.class, "16M"));
log.debug("Registring Ehcache Metrics gauges");
Set<EntityType<?>> entities = mainEntityManager.getMetamodel().getEntities();
for (EntityType<?> entity : entities) {
String name = entity.getName();
if ( name == null ) {
name = entity.getJavaType().getName();
}
Assert.notNull(name, "entity cannot exist without a identifier");
net.sf.ehcache.Cache cache = cacheManager.getCache(name);
if (cache != null) {
cache.getCacheConfiguration().setTimeToLiveSeconds(env.getProperty("cache.timeToLiveSeconds", Integer.class, CACHE_TIME_TO_LIVE));
net.sf.ehcache.Ehcache decoratedCache = InstrumentedEhcache.instrument(metricRegistry, cache);
cacheManager.replaceCacheWithDecoratedCache(cache, decoratedCache);
}
}
EhCacheCacheManager ehCacheManager = new EhCacheCacheManager();
ehCacheManager.setCacheManager(cacheManager);
return ehCacheManager;
}
}
对不起,很长的帖子。我希望它足够清楚。不要犹豫要求精确。
答案 0 :(得分:1)
我遇到了同样的问题。在调试之后,似乎application.properties文件中的属性稍后在初始化过程中被拾取,并且在初始化SessionFactory时尚未准备好。
以下可能是一个丑陋的解决方案,但它对我有用:
@Bean
public SessionFactory sessionFactory() {
final LocalSessionFactoryBuilder localSessionFactoryBuilder = new LocalSessionFactoryBuilder(dataSource);
localSessionFactoryBuilder.scanPackages(myModelPackage);
localSessionFactoryBuilder.setProperty(Environment.CACHE_REGION_FACTORY, "org.hibernate.cache.ehcache.EhCacheRegionFactory");
return localSessionFactoryBuilder.buildSessionFactory();
}
此部分将进入您的数据库配置路径。 正如您所看到的,我在会话工厂创建的早期阶段强制缓存区域工厂属性。