This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit db478261e072dcf603b8071dc47c089add4122d7 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Tue Feb 24 04:34:03 2026 -0600 HibernateConnectionSourceFactory tested --- .../AbstractHibernateConnectionSourceFactory.java | 157 ---------- .../HibernateConnectionSourceFactory.java | 328 +++++++++++---------- .../HibernateConnectionSourceFactorySpec.groovy | 123 ++++++-- 3 files changed, 280 insertions(+), 328 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java deleted file mode 100644 index f2ab6b65d4..0000000000 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.grails.orm.hibernate.connections; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; -import javax.sql.DataSource; -import org.grails.datastore.gorm.jdbc.connections.CachedDataSourceConnectionSourceFactory; -import org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory; -import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; -import org.grails.datastore.gorm.jdbc.connections.DataSourceSettingsBuilder; -import org.grails.datastore.mapping.core.connections.*; -import org.grails.orm.hibernate.cfg.Settings; -import org.hibernate.SessionFactory; -import org.springframework.core.env.PropertyResolver; - -/** - * Constructs a Hibernate {@link SessionFactory} - * - * @author Graeme Rocher - * @since 6.0 - */ -public abstract class AbstractHibernateConnectionSourceFactory - extends AbstractConnectionSourceFactory<SessionFactory, HibernateConnectionSourceSettings> { - - /** The data source connection source factory. */ - protected DataSourceConnectionSourceFactory dataSourceConnectionSourceFactory = - new CachedDataSourceConnectionSourceFactory(); - - /** - * Sets the factory for creating SQL {@link DataSource} connection sources - * - * @param dataSourceConnectionSourceFactory the data source connection source factory - */ - public void setDataSourceConnectionSourceFactory( - DataSourceConnectionSourceFactory dataSourceConnectionSourceFactory) { - this.dataSourceConnectionSourceFactory = dataSourceConnectionSourceFactory; - } - - public ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> create( - String name, HibernateConnectionSourceSettings settings) { - DataSourceSettings dataSourceSettings = settings.getDataSource(); - ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource = - dataSourceConnectionSourceFactory.create(name, dataSourceSettings); - return create(name, dataSourceConnectionSource, settings); - } - - @Override - public Serializable getConnectionSourcesConfigurationKey() { - return Settings.SETTING_DATASOURCES; - } - - @Override - public <F extends ConnectionSourceSettings> - HibernateConnectionSourceSettings buildRuntimeSettings( - String name, PropertyResolver configuration, F fallbackSettings) { - return buildSettingsWithPrefix(configuration, fallbackSettings, ""); - } - - /** - * Creates a ConnectionSource for the given DataSource - * - * @param name The name - * @param dataSourceConnectionSource The data source connection source - * @param settings The settings - * @return The ConnectionSource - */ - public abstract ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> create( - String name, - ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource, - HibernateConnectionSourceSettings settings); - - protected <F extends ConnectionSourceSettings> HibernateConnectionSourceSettings buildSettings( - String name, - PropertyResolver configuration, - F fallbackSettings, - boolean isDefaultDataSource) { - HibernateConnectionSourceSettingsBuilder builder; - HibernateConnectionSourceSettings settings; - if (isDefaultDataSource) { - String qualified = Settings.SETTING_DATASOURCES + '.' + Settings.SETTING_DATASOURCE; - builder = new HibernateConnectionSourceSettingsBuilder(configuration, "", fallbackSettings); - Map config = configuration.getProperty(qualified, Map.class, Collections.emptyMap()); - settings = builder.build(); - if (!config.isEmpty()) { - - DataSourceSettings dsfallbackSettings = null; - if (fallbackSettings instanceof HibernateConnectionSourceSettings) { - dsfallbackSettings = - ((HibernateConnectionSourceSettings) fallbackSettings).getDataSource(); - } else if (fallbackSettings instanceof DataSourceSettings) { - dsfallbackSettings = (DataSourceSettings) fallbackSettings; - } - DataSourceSettingsBuilder dataSourceSettingsBuilder = - new DataSourceSettingsBuilder(configuration, qualified, dsfallbackSettings); - DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); - settings.setDataSource(dataSourceSettings); - } - } else { - String prefix = Settings.SETTING_DATASOURCES + "." + name; - settings = buildSettingsWithPrefix(configuration, fallbackSettings, prefix); - } - return settings; - } - - private <F extends ConnectionSourceSettings> - HibernateConnectionSourceSettings buildSettingsWithPrefix( - PropertyResolver configuration, F fallbackSettings, String prefix) { - HibernateConnectionSourceSettingsBuilder builder; - HibernateConnectionSourceSettings settings; - builder = new HibernateConnectionSourceSettingsBuilder(configuration, prefix, fallbackSettings); - - DataSourceSettings dsfallbackSettings = null; - if (fallbackSettings instanceof HibernateConnectionSourceSettings) { - dsfallbackSettings = ((HibernateConnectionSourceSettings) fallbackSettings).getDataSource(); - } else if (fallbackSettings instanceof DataSourceSettings) { - dsfallbackSettings = (DataSourceSettings) fallbackSettings; - } - - settings = builder.build(); - if (prefix.length() == 0) { - // if the prefix is zero length then this is a datasource added at runtime using - // ConnectionSources.addConnectionSource - DataSourceSettingsBuilder dataSourceSettingsBuilder = - new DataSourceSettingsBuilder(configuration, prefix, dsfallbackSettings); - DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); - settings.setDataSource(dataSourceSettings); - } else { - if (configuration - .getProperty(prefix + ".dataSource", Map.class, Collections.emptyMap()) - .isEmpty()) { - DataSourceSettingsBuilder dataSourceSettingsBuilder = - new DataSourceSettingsBuilder(configuration, prefix, dsfallbackSettings); - DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); - settings.setDataSource(dataSourceSettings); - } - } - return settings; - } -} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java index 3cedcd8149..93ebaf7f0b 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java @@ -20,17 +20,25 @@ package org.grails.orm.hibernate.connections; import java.io.File; import java.io.IOException; -import java.util.Properties; +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; import javax.sql.DataSource; -import org.grails.datastore.gorm.jdbc.connections.*; + +import org.grails.datastore.gorm.jdbc.connections.CachedDataSourceConnectionSourceFactory; +import org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory; +import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; +import org.grails.datastore.gorm.jdbc.connections.DataSourceSettingsBuilder; import org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry; +import org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory; import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; -import org.grails.datastore.mapping.core.grailsversion.GrailsVersion; import org.grails.datastore.mapping.validation.ValidatorRegistry; import org.grails.orm.hibernate.HibernateEventListeners; import org.grails.orm.hibernate.cfg.HibernateMappingContext; import org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration; +import org.grails.orm.hibernate.cfg.Settings; import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder; import org.grails.orm.hibernate.support.AbstractClosureEventTriggeringInterceptor; import org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor; @@ -40,12 +48,12 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.cfg.Configuration; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.StaticMessageSource; +import org.springframework.core.env.PropertyResolver; import org.springframework.core.io.Resource; /** @@ -54,7 +62,8 @@ import org.springframework.core.io.Resource; * @author Graeme Rocher * @since 6.0 */ -public class HibernateConnectionSourceFactory extends AbstractHibernateConnectionSourceFactory +public class HibernateConnectionSourceFactory + extends AbstractConnectionSourceFactory<SessionFactory, HibernateConnectionSourceSettings> implements ApplicationContextAware, MessageSourceAware { static { @@ -62,6 +71,9 @@ public class HibernateConnectionSourceFactory extends AbstractHibernateConnectio System.setProperty("org.jboss.logging.provider", "slf4j"); } + protected DataSourceConnectionSourceFactory dataSourceConnectionSourceFactory = + new CachedDataSourceConnectionSourceFactory(); + protected HibernateMappingContext mappingContext; protected Class[] persistentClasses = new Class[0]; private ApplicationContext applicationContext; @@ -77,12 +89,10 @@ public class HibernateConnectionSourceFactory extends AbstractHibernateConnectio return persistentClasses; } - @Autowired(required = false) public void setHibernateEventListeners(HibernateEventListeners hibernateEventListeners) { this.hibernateEventListeners = hibernateEventListeners; } - @Autowired(required = false) public void setInterceptor(Interceptor interceptor) { this.interceptor = interceptor; } @@ -91,7 +101,6 @@ public class HibernateConnectionSourceFactory extends AbstractHibernateConnectio return mappingContext; } - @Override public ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> create( String name, ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource, @@ -107,187 +116,204 @@ public class HibernateConnectionSourceFactory extends AbstractHibernateConnectio String name, ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource, HibernateConnectionSourceSettings settings) { - boolean isDefault = ConnectionSource.DEFAULT.equals(name); - if (mappingContext == null) { mappingContext = new HibernateMappingContext(settings, applicationContext, persistentClasses); } HibernateConnectionSourceSettings.HibernateSettings hibernateSettings = settings.getHibernate(); - Class<? extends Configuration> configClass = hibernateSettings.getConfigClass(); + HibernateMappingContextConfiguration configuration = + resolveConfiguration(hibernateSettings.getConfigClass()); - HibernateMappingContextConfiguration configuration; - if (configClass != null) { - if (!HibernateMappingContextConfiguration.class.isAssignableFrom(configClass)) { - throw new ConfigurationException( - "The configClass setting must be a subclass for [HibernateMappingContextConfiguration]"); - } else { - configuration = - (HibernateMappingContextConfiguration) BeanUtils.instantiateClass(configClass); - } - } else { - configuration = new HibernateMappingContextConfiguration(); - } + configureValidator(configuration, dataSourceConnectionSource.getSettings()); + configureDataSource(configuration, dataSourceConnectionSource); + configureResourceLocations(configuration, hibernateSettings); + + if (interceptor != null) configuration.setInterceptor(interceptor); + if (hibernateSettings.getAnnotatedClasses() != null) + configuration.addAnnotatedClasses(hibernateSettings.getAnnotatedClasses()); + if (hibernateSettings.getAnnotatedPackages() != null) + configuration.addPackages(hibernateSettings.getAnnotatedPackages()); + if (hibernateSettings.getPackagesToScan() != null) + configuration.scanPackages(hibernateSettings.getPackagesToScan()); - if (JakartaValidatorRegistry.isAvailable() && messageSource != null) { - ValidatorRegistry registry = - new JakartaValidatorRegistry( - mappingContext, dataSourceConnectionSource.getSettings(), messageSource); - mappingContext.setValidatorRegistry(registry); - configuration.getProperties().put("jakarta.persistence.validation.factory", registry); + configureNamingStrategy(name, hibernateSettings); + + AbstractClosureEventTriggeringInterceptor eventTriggeringInterceptor = + resolveEventTriggeringInterceptor(hibernateSettings.getClosureEventTriggeringInterceptorClass()); + hibernateSettings.setEventTriggeringInterceptor(eventTriggeringInterceptor); + + configuration.setEventListeners(hibernateSettings.toHibernateEventListeners(eventTriggeringInterceptor)); + configuration.setHibernateEventListeners( + this.hibernateEventListeners != null + ? this.hibernateEventListeners + : hibernateSettings.getHibernateEventListeners()); + configuration.setHibernateMappingContext(mappingContext); + configuration.setDataSourceName(name); + configuration.setSessionFactoryBeanName( + ConnectionSource.DEFAULT.equals(name) ? "sessionFactory" : "sessionFactory_" + name); + configuration.addProperties(settings.toProperties()); + return configuration; + } + + private HibernateMappingContextConfiguration resolveConfiguration( + Class<? extends Configuration> configClass) { + if (configClass == null) return new HibernateMappingContextConfiguration(); + if (!HibernateMappingContextConfiguration.class.isAssignableFrom(configClass)) { + throw new ConfigurationException( + "The configClass setting must be a subclass for [HibernateMappingContextConfiguration]"); } + return (HibernateMappingContextConfiguration) BeanUtils.instantiateClass(configClass); + } + + private void configureValidator( + HibernateMappingContextConfiguration configuration, + DataSourceSettings dataSourceSettings) { + if (!JakartaValidatorRegistry.isAvailable() || messageSource == null) return; + ValidatorRegistry registry = + new JakartaValidatorRegistry(mappingContext, dataSourceSettings, messageSource); + mappingContext.setValidatorRegistry(registry); + configuration.getProperties().put("jakarta.persistence.validation.factory", registry); + } + private void configureDataSource( + HibernateMappingContextConfiguration configuration, + ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource) { if (applicationContext != null && applicationContext.containsBean(dataSourceConnectionSource.getName())) { - configuration.setApplicationContext(this.applicationContext); + configuration.setApplicationContext(applicationContext); } else { configuration.setDataSourceConnectionSource(dataSourceConnectionSource); } + } - Resource[] configLocations = hibernateSettings.getConfigLocations(); - if (configLocations != null) { - for (Resource resource : configLocations) { - // Load Hibernate configuration from given location. - try { - configuration.configure(resource.getURL()); - } catch (IOException e) { - throw new ConfigurationException( - "Cannot configure Hibernate config for location: " + resource.getFilename(), e); - } - } - } - - Resource[] mappingLocations = hibernateSettings.getMappingLocations(); - if (mappingLocations != null) { - // Register given Hibernate mapping definitions, contained in resource files. - for (Resource resource : mappingLocations) { - try { - configuration.addInputStream(resource.getInputStream()); - } catch (IOException e) { - throw new ConfigurationException( - "Cannot configure Hibernate config for location: " + resource.getFilename(), e); - } - } - } - - Resource[] cacheableMappingLocations = hibernateSettings.getCacheableMappingLocations(); - if (cacheableMappingLocations != null) { - // Register given cacheable Hibernate mapping definitions, read from the file system. - for (Resource resource : cacheableMappingLocations) { - try { - configuration.addCacheableFile(resource.getFile()); - } catch (IOException e) { - throw new ConfigurationException( - "Cannot configure Hibernate config for location: " + resource.getFilename(), e); - } + private void configureResourceLocations( + HibernateMappingContextConfiguration configuration, + HibernateConnectionSourceSettings.HibernateSettings hibernateSettings) { + applyResources(hibernateSettings.getConfigLocations(), + r -> configuration.configure(r.getURL())); + applyResources(hibernateSettings.getMappingLocations(), + r -> configuration.addInputStream(r.getInputStream())); + applyResources(hibernateSettings.getCacheableMappingLocations(), + r -> configuration.addCacheableFile(r.getFile())); + applyResources(hibernateSettings.getMappingJarLocations(), + r -> configuration.addJar(r.getFile())); + applyResources(hibernateSettings.getMappingDirectoryLocations(), r -> { + File file = r.getFile(); + if (!file.isDirectory()) { + throw new IllegalArgumentException( + "Mapping directory location [" + r + "] does not denote a directory"); } - } + configuration.addDirectory(file); + }); + } - Resource[] mappingJarLocations = hibernateSettings.getMappingJarLocations(); - if (mappingJarLocations != null) { - // Register given Hibernate mapping definitions, contained in jar files. - for (Resource resource : mappingJarLocations) { - try { - configuration.addJar(resource.getFile()); - } catch (IOException e) { - throw new ConfigurationException( - "Cannot configure Hibernate config for location: " + resource.getFilename(), e); - } - } - } + @FunctionalInterface + private interface ResourceConfigurer { + void apply(Resource resource) throws IOException; + } - Resource[] mappingDirectoryLocations = hibernateSettings.getMappingDirectoryLocations(); - if (mappingDirectoryLocations != null) { - // Register all Hibernate mapping definitions in the given directories. - for (Resource resource : mappingDirectoryLocations) { - File file; - try { - file = resource.getFile(); - } catch (IOException e) { - throw new ConfigurationException( - "Cannot configure Hibernate config for location: " + resource.getFilename(), e); - } - if (!file.isDirectory()) { - throw new IllegalArgumentException( - "Mapping directory location [" + resource + "] does not denote a directory"); - } - configuration.addDirectory(file); + private static void applyResources(Resource[] resources, ResourceConfigurer configurer) { + if (resources == null) return; + for (Resource resource : resources) { + try { + configurer.apply(resource); + } catch (IOException e) { + throw new ConfigurationException( + "Cannot configure Hibernate config for location: " + resource.getFilename(), e); } } + } - if (this.interceptor != null) { - configuration.setInterceptor(this.interceptor); + private static void configureNamingStrategy( + String name, HibernateConnectionSourceSettings.HibernateSettings hibernateSettings) { + try { + Class<? extends PhysicalNamingStrategy> namingStrategy = hibernateSettings.getNaming_strategy(); + if (namingStrategy != null) GrailsDomainBinder.configureNamingStrategy(name, namingStrategy); + } catch (Throwable e) { + throw new ConfigurationException("Error configuring naming strategy: " + e.getMessage(), e); } + } - Class[] annotatedClasses = hibernateSettings.getAnnotatedClasses(); - if (annotatedClasses != null) { - configuration.addAnnotatedClasses(annotatedClasses); - } + private static AbstractClosureEventTriggeringInterceptor resolveEventTriggeringInterceptor( + Class<? extends AbstractClosureEventTriggeringInterceptor> clazz) { + return clazz != null + ? BeanUtils.instantiateClass(clazz) + : new ClosureEventTriggeringInterceptor(); + } - String[] annotatedPackages = hibernateSettings.getAnnotatedPackages(); - if (annotatedPackages != null) { - configuration.addPackages(annotatedPackages); - } + public void setDataSourceConnectionSourceFactory( + DataSourceConnectionSourceFactory dataSourceConnectionSourceFactory) { + this.dataSourceConnectionSourceFactory = dataSourceConnectionSourceFactory; + } - String[] packagesToScan = hibernateSettings.getPackagesToScan(); - if (packagesToScan != null) { - configuration.scanPackages(packagesToScan); - } + public ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> create( + String name, HibernateConnectionSourceSettings settings) { + ConnectionSource<DataSource, DataSourceSettings> dataSourceConnectionSource = + dataSourceConnectionSourceFactory.create(name, settings.getDataSource()); + return create(name, dataSourceConnectionSource, settings); + } - Class<? extends AbstractClosureEventTriggeringInterceptor> - closureEventTriggeringInterceptorClass = - hibernateSettings.getClosureEventTriggeringInterceptorClass(); + @Override + public Serializable getConnectionSourcesConfigurationKey() { + return Settings.SETTING_DATASOURCES; + } - AbstractClosureEventTriggeringInterceptor eventTriggeringInterceptor; + @Override + public <F extends ConnectionSourceSettings> HibernateConnectionSourceSettings buildRuntimeSettings( + String name, PropertyResolver configuration, F fallbackSettings) { + return buildSettingsWithPrefix(configuration, fallbackSettings, ""); + } - if (closureEventTriggeringInterceptorClass == null) { - eventTriggeringInterceptor = new ClosureEventTriggeringInterceptor(); - } else { - eventTriggeringInterceptor = - BeanUtils.instantiateClass(closureEventTriggeringInterceptorClass); + @Override + protected <F extends ConnectionSourceSettings> HibernateConnectionSourceSettings buildSettings( + String name, + PropertyResolver configuration, + F fallbackSettings, + boolean isDefaultDataSource) { + if (isDefaultDataSource) { + String qualified = Settings.SETTING_DATASOURCES + '.' + Settings.SETTING_DATASOURCE; + HibernateConnectionSourceSettings settings = + new HibernateConnectionSourceSettingsBuilder(configuration, "", fallbackSettings).build(); + Map config = configuration.getProperty(qualified, Map.class, Collections.emptyMap()); + if (!config.isEmpty()) { + DataSourceSettings dsFallback = extractDataSourceFallback(fallbackSettings); + settings.setDataSource( + new DataSourceSettingsBuilder(configuration, qualified, dsFallback).build()); + } + return settings; } + return buildSettingsWithPrefix( + configuration, fallbackSettings, Settings.SETTING_DATASOURCES + "." + name); + } - hibernateSettings.setEventTriggeringInterceptor(eventTriggeringInterceptor); - - try { - Class<? extends PhysicalNamingStrategy> namingStrategy = - hibernateSettings.getNaming_strategy(); - if (namingStrategy != null) { - GrailsDomainBinder.configureNamingStrategy(name, namingStrategy); - } - } catch (Throwable e) { - throw new ConfigurationException("Error configuring naming strategy: " + e.getMessage(), e); + private <F extends ConnectionSourceSettings> HibernateConnectionSourceSettings buildSettingsWithPrefix( + PropertyResolver configuration, F fallbackSettings, String prefix) { + DataSourceSettings dsFallback = extractDataSourceFallback(fallbackSettings); + HibernateConnectionSourceSettings settings = + new HibernateConnectionSourceSettingsBuilder(configuration, prefix, fallbackSettings).build(); + if (prefix.isEmpty() + || configuration.getProperty(prefix + ".dataSource", Map.class, Collections.emptyMap()).isEmpty()) { + settings.setDataSource( + new DataSourceSettingsBuilder(configuration, prefix, dsFallback).build()); } + return settings; + } - configuration.setEventListeners( - hibernateSettings.toHibernateEventListeners(eventTriggeringInterceptor)); - HibernateEventListeners hibernateEventListeners = - hibernateSettings.getHibernateEventListeners(); - configuration.setHibernateEventListeners( - this.hibernateEventListeners != null - ? this.hibernateEventListeners - : hibernateEventListeners); - configuration.setHibernateMappingContext(mappingContext); - configuration.setDataSourceName(name); - configuration.setSessionFactoryBeanName( - isDefault ? "sessionFactory" : "sessionFactory_" + name); - Properties hibernateProperties = settings.toProperties(); - configuration.addProperties(hibernateProperties); - return configuration; + private static <F extends ConnectionSourceSettings> DataSourceSettings extractDataSourceFallback( + F fallbackSettings) { + if (fallbackSettings instanceof HibernateConnectionSourceSettings hcs) { + return hcs.getDataSource(); + } + if (fallbackSettings instanceof DataSourceSettings ds) { + return ds; + } + return null; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (applicationContext != null) { this.applicationContext = applicationContext; this.messageSource = applicationContext; - if (!GrailsVersion.isAtLeastMajorMinor(3, 3)) { - SpringDataSourceConnectionSourceFactory springDataSourceConnectionSourceFactory = - new SpringDataSourceConnectionSourceFactory(); - springDataSourceConnectionSourceFactory.setApplicationContext(applicationContext); - this.dataSourceConnectionSourceFactory = springDataSourceConnectionSourceFactory; - } - } } @Override diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy index e15dda5766..4bd8abb21f 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy @@ -19,43 +19,126 @@ package org.grails.orm.hibernate.connections import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.connections.ConnectionSource -import org.hibernate.SessionFactory +import org.grails.datastore.mapping.core.exceptions.ConfigurationException +import org.grails.orm.hibernate.cfg.HibernateMappingContext +import org.hibernate.cfg.Configuration import org.hibernate.dialect.H2Dialect -import org.hibernate.query.criteria.JpaCriteriaQuery -import spock.lang.Specification +import org.springframework.context.support.StaticMessageSource /** - * Created by graemerocher on 06/07/2016. + * Specs for {@link HibernateConnectionSourceFactory} using the shared H2 datastore + * infrastructure from {@link HibernateGormDatastoreSpec}. */ -class HibernateConnectionSourceFactorySpec extends Specification { +class HibernateConnectionSourceFactorySpec extends HibernateGormDatastoreSpec { - void "Test hibernate connection factory"() { - when:"A factory is used to create a session factory" + def setupSpec() { + manager.addAllDomainClasses([Foo]) + } - HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) - Map config = [ - 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", - 'dataSource.dbCreate': 'update', - 'dataSource.dialect': H2Dialect.name, - 'dataSource.formatSql': 'true', - 'hibernate.flush.mode': 'COMMIT', - 'hibernate.cache.queries': 'true', - 'hibernate.hbm2ddl.auto': 'create' + private static Map<String, String> h2Config() { + [ + 'dataSource.url' : "jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", + 'dataSource.dbCreate' : 'update', + 'dataSource.dialect' : H2Dialect.name, + 'dataSource.formatSql' : 'true', + 'hibernate.flush.mode' : 'COMMIT', + 'hibernate.cache.queries': 'true', + 'hibernate.hbm2ddl.auto' : 'create', ] - def connectionSource = factory.create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(config)) + } + + void "Test hibernate connection factory creates an open session factory"() { + when: "A factory is used to create a session factory" + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + def connectionSource = factory.create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(h2Config())) def query = connectionSource.source.getCriteriaBuilder().createQuery(Foo) query.select(query.from(Foo)) - then:"The session factory is created" + + then: "The session factory is created and queryable" connectionSource.source.openSession().createQuery(query).list().size() == 0 - when:"The connection source is closed" + when: "The connection source is closed" connectionSource.close() - then:"The session factory is closed" + then: "The session factory is closed" connectionSource.source.isClosed() } + + void "getPersistentClasses returns the classes passed to the constructor"() { + when: + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + + then: + factory.persistentClasses == [Foo] as Class[] + } + + void "getMappingContext is a HibernateMappingContext populated with the entity after create()"() { + given: + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + def connectionSource = factory.create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(h2Config())) + + expect: + factory.mappingContext instanceof HibernateMappingContext + factory.mappingContext.getPersistentEntity(Foo.name) != null + + cleanup: + connectionSource?.close() + } + + void "create() with a named connection source propagates the name"() { + given: + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + def connectionSource = factory.create("secondary", DatastoreUtils.createPropertyResolver(h2Config())) + + expect: + connectionSource.name == "secondary" + + cleanup: + connectionSource?.close() + } + + void "buildConfiguration throws ConfigurationException for a non-HibernateMappingContextConfiguration configClass"() { + given: "Settings with a configClass that is not a subclass of HibernateMappingContextConfiguration" + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + def settings = new HibernateConnectionSourceSettings() + settings.hibernate.configClass = Configuration // plain Configuration, not the subclass + + // Provide a minimal DataSource connection source to drive buildConfiguration + def dsConfig = [ + 'dataSource.url' : "jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", + 'dataSource.dbCreate' : 'update', + 'dataSource.dialect' : H2Dialect.name, + 'hibernate.hbm2ddl.auto': 'create', + ] + def dataSourceCs = new org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory() + .create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(dsConfig)) + + when: + factory.buildConfiguration(ConnectionSource.DEFAULT, dataSourceCs, settings) + + then: + thrown(ConfigurationException) + } + + void "setMessageSource stores the provided message source"() { + given: + HibernateConnectionSourceFactory factory = new HibernateConnectionSourceFactory(Foo) + def source = new StaticMessageSource() + + when: + factory.setMessageSource(source) + + then: + factory.messageSource.is(source) + } + + void "the shared datastore mapping context has Foo registered as a persistent entity"() { + expect: + getMappingContext().getPersistentEntity(Foo.name) != null + } } @Entity
