This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 0d2c60704c50b80d863e05a3a118e158551ce259 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sun Mar 22 13:25:05 2026 -0500 hibernate 7: Internally DataSource Connection.DEFAULT value was incorrect, still support legacy value hardcoded --- grails-data-hibernate7/core/ISSUES.md | 98 ++++++++++++++++++++++ .../orm/hibernate/GrailsHibernateTemplate.java | 17 ++-- .../grails/orm/hibernate/HibernateDatastore.java | 51 ++++++----- .../domainbinding/binder/GrailsDomainBinder.java | 3 +- .../hibernate/GrailsHibernatePersistentEntity.java | 49 +++++------ .../util/MultiTenantFilterBinder.java | 3 +- .../HibernateConnectionSourceFactory.java | 15 ++-- .../proxy/GroovyProxyInterceptorLogic.java | 26 +++--- .../grails/orm/hibernate/query/HibernateAlias.java | 18 +--- .../orm/hibernate/query/HqlQueryContext.java | 42 +++++----- .../orm/hibernate/query/JpaFromProvider.java | 2 +- .../orm/hibernate/HibernateDatastoreSpec.groovy | 77 ++++++++++++++--- .../cfg/GrailsHibernatePersistentEntitySpec.groovy | 3 +- .../cfg/HibernateMappingContextSpec.groovy | 5 +- .../cfg/domainbinding/binder/RootBinderSpec.groovy | 7 +- .../domainbinding/binder/SubClassBinderSpec.groovy | 10 +-- .../mapping/core/connections/ConnectionSource.java | 9 +- .../datastore/mapping/model/MappingContext.java | 2 +- 18 files changed, 294 insertions(+), 143 deletions(-) diff --git a/grails-data-hibernate7/core/ISSUES.md b/grails-data-hibernate7/core/ISSUES.md index 524d83cb6d..e9194b2bc3 100644 --- a/grails-data-hibernate7/core/ISSUES.md +++ b/grails-data-hibernate7/core/ISSUES.md @@ -1,7 +1,105 @@ # Known Issues in Hibernate 7 Migration +## [TODO] Review impact of changing `ConnectionSource.DEFAULT` to "default" +**Description:** +The value of `ConnectionSource.DEFAULT` was changed from `"DEFAULT"` to `"default"` (lowercase) to align with Grails 7 official conventions. +A new constant `ConnectionSource.OLD_DEFAULT = "DEFAULT"` was added for backward compatibility. +In Grails 7: +- GORM Connection Name: `"default"` (via `ConnectionSource.DEFAULT`) +- Spring Bean ID: `"dataSource"` +- Configuration Key: `"dataSource"` +**Actions taken in H7:** +- `HibernateDatastore.getDatastoreForConnection` supports `"dataSource"`, `ConnectionSource.DEFAULT` ("default"), and `ConnectionSource.OLD_DEFAULT` ("DEFAULT"). +- Raw `"default"` and `"DEFAULT"` strings in H7 production code and key tests have been replaced with `ConnectionSource.DEFAULT`. +- `HibernateMappingContextConfiguration` and `HibernateDatastore` correctly use `ConnectionSource.DEFAULT` for the primary datasource name. +**Risk & Potential Propagation:** +- This change might affect other GORM modules (Neo4j, MongoDB, etc.) if they rely on the uppercase `"DEFAULT"` string literal and don't yet support the lowercase `"default"`. +- Production systems referencing the raw string `"DEFAULT"` should be encouraged to use the `ConnectionSource.DEFAULT` constant. +**Action Required:** +- Audit other GORM implementations for consistency. + +## Static Analysis Violations (hibernate7-core) + +### Checkstyle +| Class | Line | Error | +|-------|------|-------| +| `org.grails.orm.hibernate.proxy.HibernateProxyHandler` | 119-121 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.proxy.ByteBuddyGroovyInterceptor` | 67 | '+' should be on the previous line. | +| `org.grails.orm.hibernate.proxy.ByteBuddyGroovyInterceptor` | 71-72 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.proxy.GroovyProxyInterceptorLogic` | 44 | '&&' should be on the previous line. | +| `org.grails.orm.hibernate.proxy.GroovyProxyInterceptorLogic` | 64-67 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.access.TraitPropertyAccessStrategy` | 72 | '&&' should be on the previous line. | +| `org.grails.orm.hibernate.access.TraitPropertyAccessStrategy` | 73 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.access.TraitPropertyAccessStrategy` | 80-113 | '+' should be on the previous line. (Multiple occurrences) | +| `org.grails.orm.hibernate.HibernateDatastore` | 34 | 'javax.sql.DataSource' should be separated from previous imports. | +| `org.grails.orm.hibernate.HibernateDatastore` | 332 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.HibernateDatastore` | 339-823 | '+' should be on the previous line. (Multiple occurrences) | +| `org.grails.orm.hibernate.HibernateDatastore` | 927 | '?' should be on the previous line. | +| `org.grails.orm.hibernate.HibernateDatastore` | 928 | ':' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.TableForManyCalculator` | 81 | '+' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider` | 92 | '?' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider` | 93 | ':' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher` | 27 | '?' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher` | 28 | ':' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator` | 73 | '?' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator` | 75 | ':' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehavior` | 107 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher` | 69-81 | '+' should be on the previous line. (Multiple occurrences) | +| `org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder` | 107-108 | '||' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder` | 109 | '&&' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher` | 52-53 | '+' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnBinder` | 130-149 | '+' should be on the previous line. (Multiple occurrences) | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.JoinedSubClassBinder` | 93-94 | '+' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder` | 105 | '?' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder` | 107 | ':' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.UnionSubclassBinder` | 89-90 | '+' should be on the previous line. | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.ForeignKeyOneToOneBinder` | 71 | '&&' should be on the previous line. | + +### PMD +| Class | Line | Error | Rule | +|-------|------|-------|------| +| `org.grails.orm.hibernate.GrailsHibernateTemplate` | 341 | New exception is thrown in catch block, original stack trace may be lost | PreserveStackTrace | +| `org.grails.orm.hibernate.HibernateDatastore` | 661 | Avoid using Literals in Conditional Statements | AvoidLiteralsInIfCondition | +| `org.grails.orm.hibernate.cfg.GrailsHibernateUtil` | 274 | Position literals first in String comparisons | LiteralsFirstInComparisons | +| `org.grails.orm.hibernate.cfg.GrailsHibernateUtil` | 292 | Logger calls should be surrounded by log level guards. | GuardLogStatement | +| `org.grails.orm.hibernate.cfg.GrailsHibernateUtil` | 294 | Logger calls should be surrounded by log level guards. | GuardLogStatement | +| `org.grails.orm.hibernate.cfg.HibernateMappingContext` | 123 | Avoid reassigning parameters such as 'name' | AvoidReassigningParameters | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 106 | Field 'hibernateMappingContext' is of non-serializable type | NonSerializableClass | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 108 | Field 'hibernateEventListeners' is of non-serializable type | NonSerializableClass | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 114 | Field 'namingStrategyProvider' is of non-serializable type | NonSerializableClass | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 146 | The String literal "false" appears 5 times in this file | AvoidDuplicateLiterals | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 187 | The method 'addAnnotatedClasses(Class...)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 207 | The method 'addPackages(String...)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | 348 | The method 'sessionFactoryClosed(SessionFactory)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.IdentityEnumType$BidiEnumMap` | 203 | Logger calls should be surrounded by log level guards. | GuardLogStatement | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder` | 69 | Avoid unused local variables such as 'table'. | UnusedLocalVariable | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder` | 78 | Avoid unused local variables such as 'table'. | UnusedLocalVariable | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder` | 107 | Switch statements should be exhaustive, add a default case | SwitchStmtsShouldHaveDefault | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.RootBinder` | 75 | Logger calls should be surrounded by log level guards. | GuardLogStatement | +| `org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder` | 36 | Avoid unused constructor parameters such as 'ignore'. | UnusedFormalParameter | +| `org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsNativeGenerator` | 73 | You should not modify visibility using setAccessible() | AvoidAccessibilityAlteration | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity` | 50 | The method 'getMappedForm()' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation` | 89 | The method 'isBidirectionalManyToOneWithListMapping(Property)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation` | 103 | The method 'getTypeName(Class, PropertyConfig, Mapping)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateBasicProperty` | 38 | The method 'getCollection()' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateBasicProperty` | 42 | The method 'setCollection(Collection)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedCollectionProperty` | 43 | The method 'getCollection()' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedCollectionProperty` | 47 | The method 'setCollection(Collection)' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedPersistentEntity` | 35 | The method 'getMappedForm()' is missing an @Override annotation. | MissingOverride | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateIdentityMapping` | 60 | Returning 'DEFAULT_IDENTITY_MAPPING' may expose an internal array. | MethodReturnsInternalArray | +| `org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty` | 44 | The method 'getReferencedEntityName()' is missing an @Override annotation. | MissingOverride | + +### SpotBugs +| Class | Line | Error | Bug Type | +|-------|------|-------|----------| +| `org.grails.orm.hibernate.query.PagedResultList` | 50-93 | Class shadows the simple name of the superclass | NM_SAME_SIMPLE_NAME_AS_SUPERCLASS | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | N/A | Non-serializable field `hibernateEventListeners` | SE_BAD_FIELD | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | N/A | Non-serializable field `hibernateMappingContext` | SE_BAD_FIELD | +| `org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration` | N/A | Non-serializable field `namingStrategyProvider` | SE_BAD_FIELD | +| `org.grails.orm.hibernate.proxy.ByteBuddyGroovyInterceptor` | N/A | Potential null pointer dereference in proxy logic | NP_NULL_ON_SOME_PATH | +| `org.grails.orm.hibernate.proxy.ByteBuddyGroovyProxyFactory` | N/A | Class implements Serializable but doesn't define serialVersionUID | SE_NO_SERIALVERSIONID | diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java index d44afc3747..60049f9100 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; - import javax.sql.DataSource; import groovy.lang.Closure; @@ -148,7 +147,8 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { @Override public <T> T execute(Closure<T> callable) { - HibernateCallback<T> hibernateCallback = DefaultGroovyMethods.asType(callable, HibernateCallback.class); + @SuppressWarnings("unchecked") + HibernateCallback<T> hibernateCallback = (HibernateCallback<T>) DefaultGroovyMethods.asType(callable, HibernateCallback.class); return execute(hibernateCallback); } @@ -207,8 +207,8 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { (ConnectionHolder) TransactionSynchronizationManager.unbindResourceIfPossible(dataSource); // if there is a connection holder and it holds an open connection close it try { - if (connectionHolder != null && - !connectionHolder.getConnection().isClosed()) { + if (connectionHolder != null + && !connectionHolder.getConnection().isClosed()) { Connection conn = connectionHolder.getConnection(); DataSourceUtils.releaseConnection(conn, dataSource); } @@ -216,8 +216,8 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { // ignore, connection closed already? if (LOG.isDebugEnabled()) { LOG.debug( - "Could not close opened JDBC connection. Did the application close the connection manually?: " + - e.getMessage()); + "Could not close opened JDBC connection. Did the application close the connection manually?: " + + e.getMessage()); } } } finally { @@ -284,8 +284,8 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { } protected boolean shouldPassReadOnlyToHibernate() { - if ((passReadOnlyToHibernate || osivReadOnly) && - TransactionSynchronizationManager.hasResource(getSessionFactory())) { + if ((passReadOnlyToHibernate || osivReadOnly) + && TransactionSynchronizationManager.hasResource(getSessionFactory())) { if (TransactionSynchronizationManager.isActualTransactionActive()) { return passReadOnlyToHibernate && TransactionSynchronizationManager.isCurrentTransactionReadOnly(); } else { @@ -338,6 +338,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { throw convertHibernateAccessException(ex); } catch (PersistenceException ex) { if (ex.getCause() instanceof HibernateException) { + // @SuppressWarnings("PMD.PreserveStackTrace") throw SessionFactoryUtils.convertHibernateAccessException((HibernateException) ex.getCause()); } throw ex; diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java index 07f32bf806..23262b6a9b 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java @@ -31,7 +31,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Callable; - import javax.sql.DataSource; import groovy.lang.Closure; @@ -109,7 +108,6 @@ import org.grails.datastore.mapping.multitenancy.resolvers.FixedTenantResolver; import org.grails.datastore.mapping.transactions.TransactionCapableDatastore; import org.grails.datastore.mapping.validation.ValidatorRegistry; import org.grails.orm.hibernate.cfg.HibernateMappingContext; -import org.grails.orm.hibernate.cfg.MappingCacheHolder; import org.grails.orm.hibernate.cfg.Settings; import org.grails.orm.hibernate.connections.HibernateConnectionSource; import org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory; @@ -219,7 +217,7 @@ public class HibernateDatastore extends AbstractDatastore this.connectionSources = connectionSources; final HibernateConnectionSource defaultConnectionSource = (HibernateConnectionSource) connectionSources.getDefaultConnectionSource(); - this.dataSourceName = defaultConnectionSource.getName(); + this.dataSourceName = ConnectionSource.DEFAULT; this.sessionFactory = defaultConnectionSource.getSource(); HibernateConnectionSourceSettings settings = defaultConnectionSource.getSettings(); HibernateConnectionSourceSettings.HibernateSettings hibernateSettings = settings.getHibernate(); @@ -330,16 +328,15 @@ public class HibernateDatastore extends AbstractDatastore @Override public HibernateDatastore getDatastoreForConnection(String connectionName) { - if (connectionName.equals(Settings.SETTING_DATASOURCE) || - connectionName.equals(ConnectionSource.DEFAULT)) { + if (Settings.SETTING_DATASOURCE.equals(connectionName) + || ConnectionSource.DEFAULT.equals(connectionName)) { return parent; } else { HibernateDatastore hibernateDatastore = parent.datastoresByConnectionSource.get(connectionName); if (hibernateDatastore == null) { throw new ConfigurationException( - "DataSource not found for name [" + - connectionName + - "] in configuration. Please check your multiple data sources configuration and try again."); + "DataSource not found for name [" + connectionName + + "] in configuration. Please check your multiple data sources configuration and try again."); } return hibernateDatastore; } @@ -576,6 +573,7 @@ public class HibernateDatastore extends AbstractDatastore /** * @return The {@link org.springframework.transaction.PlatformTransactionManager} instance */ + @Override public GrailsHibernateTransactionManager getTransactionManager() { return transactionManager; } @@ -588,14 +586,15 @@ public class HibernateDatastore extends AbstractDatastore */ @Override public HibernateDatastore getDatastoreForConnection(String connectionName) { - if (Settings.SETTING_DATASOURCE.equals(connectionName) || ConnectionSource.DEFAULT.equals(connectionName)) { + if (Settings.SETTING_DATASOURCE.equals(connectionName) + || ConnectionSource.DEFAULT.equals(connectionName) + || ConnectionSource.OLD_DEFAULT.equals(connectionName)) { return this; } else { HibernateDatastore hibernateDatastore = this.datastoresByConnectionSource.get(connectionName); if (hibernateDatastore == null) { - throw new ConfigurationException("DataSource not found for name [" + - connectionName + - "] in configuration. Please check your multiple data sources configuration and try again."); + throw new ConfigurationException("DataSource not found for name [" + connectionName + + "] in configuration. Please check your multiple data sources configuration and try again."); } return hibernateDatastore; } @@ -661,7 +660,7 @@ public class HibernateDatastore extends AbstractDatastore schemaHandler.resolveSchemaNames(defaultConnectionSource.getDataSource()); for (String schemaName : schemaNames) { // skip common internal schemas - if (schemaName.equals("INFORMATION_SCHEMA") || schemaName.equals("PUBLIC")) continue; + if ("INFORMATION_SCHEMA".equals(schemaName) || "PUBLIC".equals(schemaName)) continue; for (String connectionName : datastoresByConnectionSource.keySet()) { if (schemaName.equalsIgnoreCase(connectionName)) { allQualifiers.add(connectionName); @@ -689,6 +688,7 @@ public class HibernateDatastore extends AbstractDatastore return new HibernateSession(this, sessionFactory); } + @Override public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException { if (applicationContext instanceof ConfigurableApplicationContext) { super.setApplicationContext(applicationContext); @@ -764,7 +764,9 @@ public class HibernateDatastore extends AbstractDatastore try { connectionSources.close(); } catch (IOException e) { - LOG.error("There was an error shutting down GORM for an entity: {}", e.getMessage(), e); + if (LOG.isErrorEnabled()) { + LOG.error("There was an error shutting down GORM for an entity: {}", e.getMessage(), e); + } } } finally { getMappingContext().getMappingCacheHolder().clear(); @@ -773,7 +775,9 @@ public class HibernateDatastore extends AbstractDatastore this.gormEnhancer.close(); } } catch (IOException e) { - LOG.error("There was an error shutting down GORM enhancer", e); + if (LOG.isErrorEnabled()) { + LOG.error("There was an error shutting down GORM enhancer", e); + } } destroyed = true; } @@ -817,16 +821,15 @@ public class HibernateDatastore extends AbstractDatastore private void addTenantForSchemaInternal(final String schemaName) { if (multiTenantMode != MultiTenancySettings.MultiTenancyMode.SCHEMA) { throw new ConfigurationException( - "The method [addTenantForSchema] can only be called with multi-tenancy mode SCHEMA. Current mode is: " + - multiTenantMode); + "The method [addTenantForSchema] can only be called with multi-tenancy mode SCHEMA. Current mode is: " + + multiTenantMode); } HibernateConnectionSourceFactory factory = (HibernateConnectionSourceFactory) connectionSources.getFactory(); HibernateConnectionSource defaultConnectionSource = (HibernateConnectionSource) connectionSources.getDefaultConnectionSource(); HibernateConnectionSourceSettings tenantSettings; try { - tenantSettings = (HibernateConnectionSourceSettings) - connectionSources.getDefaultConnectionSource().getSettings().clone(); + tenantSettings = (HibernateConnectionSourceSettings) connectionSources.getDefaultConnectionSource().getSettings().clone(); } catch (CloneNotSupportedException e) { throw new ConfigurationException("Couldn't clone default Hibernate settings! " + e.getMessage(), e); } @@ -921,9 +924,9 @@ public class HibernateDatastore extends AbstractDatastore @Override public MultiTenancySettings.MultiTenancyMode getMultiTenancyMode() { - return this.multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA ? - MultiTenancySettings.MultiTenancyMode.DATABASE : - this.multiTenantMode; + return this.multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA + ? MultiTenancySettings.MultiTenancyMode.DATABASE + : this.multiTenantMode; } @Override @@ -1111,7 +1114,9 @@ public class HibernateDatastore extends AbstractDatastore try { destroy(); } catch (Exception e) { - LOG.error("Error closing hibernate datastore: {}", e.getMessage(), e); + if (LOG.isErrorEnabled()) { + LOG.error("Error closing hibernate datastore: {}", e.getMessage(), e); + } } } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java index f16f5cd717..eabaa2d192 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java @@ -18,6 +18,7 @@ */ package org.grails.orm.hibernate.cfg.domainbinding.binder; +import org.grails.datastore.mapping.core.connections.ConnectionSource; import org.hibernate.boot.ResourceStreamLocator; import org.hibernate.boot.internal.MetadataBuildingContextRootImpl; import org.hibernate.boot.model.TypeContributions; @@ -116,7 +117,7 @@ public class GrailsDomainBinder implements AdditionalMappingContributor, TypeCon ResourceStreamLocator resourceStreamLocator, MetadataBuildingContext buildingContext) { this.metadataBuildingContext = new MetadataBuildingContextRootImpl( - "default", + ConnectionSource.DEFAULT, metadataCollector.getBootstrapContext(), metadataCollector.getMetadataBuildingOptions(), metadataCollector, diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java index 84f119d6a1..e85c6e4f38 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java @@ -28,6 +28,7 @@ import java.util.stream.Stream; import jakarta.annotation.Nonnull; +import org.hibernate.FetchMode; import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.mapping.PersistentClass; @@ -233,9 +234,7 @@ public interface GrailsHibernatePersistentEntity extends PersistentEntity { } default List<HibernatePersistentEntity> getChildEntities(String dataSourceName) { - return getMappingContext() - .getDirectChildEntities(this) - .stream() + return getMappingContext().getDirectChildEntities(this).stream() .filter(HibernatePersistentEntity.class::isInstance) .map(HibernatePersistentEntity.class::cast) .filter(persistentEntity -> persistentEntity.usesConnectionSource(dataSourceName)) @@ -301,9 +300,9 @@ public interface GrailsHibernatePersistentEntity extends PersistentEntity { } private static String resolveDiscriminatorValue(DiscriminatorConfig discriminatorConfig) { - return discriminatorConfig.getColumn() != null ? - discriminatorConfig.getColumn().getName() : - discriminatorConfig.getFormula(); + return discriminatorConfig.getColumn() != null + ? discriminatorConfig.getColumn().getName() + : discriminatorConfig.getFormula(); } default List<HibernatePersistentProperty> getHibernatePersistentProperties() { @@ -312,12 +311,13 @@ public interface GrailsHibernatePersistentEntity extends PersistentEntity { .map(HibernatePersistentProperty.class::cast) .toList()); properties.sort((p1, p2) -> { - if (p1 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty && - !(p2 instanceof - org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty)) { + if (p1 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty + && !(p2 + instanceof + org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty)) { return -1; - } else if (!(p1 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty) && - p2 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty) { + } else if (!(p1 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty) + && p2 instanceof org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty) { return 1; } return p1.getName().compareTo(p2.getName()); @@ -348,23 +348,14 @@ public interface GrailsHibernatePersistentEntity extends PersistentEntity { return false; } - org.grails.orm.hibernate.cfg.PropertyConfig config = property.getMappedForm(); - - if (property instanceof HibernateAssociation) { - // Explicit fetch: 'join' implies eager (not lazy) and takes precedence in Hibernate - if (config != null && org.hibernate.FetchMode.JOIN.equals(config.getFetchMode())) { - return false; - } - if (config != null && config.getLazy() != null) { - return config.getLazy(); - } - return true; - } - - if (config != null && config.getLazy() != null) { - return config.getLazy(); - } - - return false; + return Optional.ofNullable(property.getMappedForm()) + .map(config -> { + if (property instanceof HibernateAssociation && + FetchMode.JOIN.equals(config.getFetchMode())) { + return false; + } + return config.getLazy(); + }) + .orElseGet(() -> property instanceof HibernateAssociation); } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java index 0d332dd5b2..9ae540fb11 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java @@ -81,8 +81,7 @@ public class MultiTenantFilterBinder { * @return null as it's redundant for single table subclasses */ @Nullable - public FilterDefinition bind( - @Nonnull HibernatePersistentEntity entity, @Nonnull SingleTableSubclass subclass) { + public FilterDefinition bind(@Nonnull HibernatePersistentEntity entity, @Nonnull SingleTableSubclass subclass) { return null; // Redundant for SingleTableSubclass } 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 52e126bfe3..a8695cdd47 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 @@ -23,7 +23,6 @@ import java.io.IOException; import java.io.Serializable; import java.util.Collections; import java.util.Map; - import javax.sql.DataSource; import jakarta.annotation.Nullable; @@ -57,7 +56,6 @@ 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.ClosureEventTriggeringInterceptor; /** @@ -145,11 +143,12 @@ public class HibernateConnectionSourceFactory resolveEventTriggeringInterceptor(hibernateSettings.getClosureEventTriggeringInterceptorClass()); hibernateSettings.setEventTriggeringInterceptor(eventTriggeringInterceptor); - configuration.setEventListeners(hibernateSettings.toHibernateEventListeners(eventTriggeringInterceptor)); + configuration.setEventListeners(HibernateConnectionSourceSettings.HibernateSettings.toHibernateEventListeners( + eventTriggeringInterceptor)); configuration.setHibernateEventListeners( - this.hibernateEventListeners != null ? - this.hibernateEventListeners : - hibernateSettings.getHibernateEventListeners()); + this.hibernateEventListeners != null + ? this.hibernateEventListeners + : hibernateSettings.getHibernateEventListeners()); configuration.setHibernateMappingContext(mappingContext); configuration.setDataSourceName(name); configuration.setSessionFactoryBeanName( @@ -288,8 +287,8 @@ public class HibernateConnectionSourceFactory DataSourceSettings dsFallback = extractDataSourceFallback(fallbackSettings); HibernateConnectionSourceSettings settings = new HibernateConnectionSourceSettingsBuilder(configuration, prefix, fallbackSettings).build(); - if (prefix.isEmpty() || - configuration + if (prefix.isEmpty() + || configuration .getProperty(prefix + ".dataSource", Map.class, Collections.emptyMap()) .isEmpty()) { settings.setDataSource(new DataSourceSettingsBuilder(configuration, prefix, dsFallback).build()); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GroovyProxyInterceptorLogic.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GroovyProxyInterceptorLogic.java index c972745ca5..2a7b9c9b89 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GroovyProxyInterceptorLogic.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GroovyProxyInterceptorLogic.java @@ -24,6 +24,7 @@ import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import org.codehaus.groovy.runtime.HandleMetaClass; import org.codehaus.groovy.runtime.InvokerHelper; + import org.grails.datastore.gorm.proxy.ProxyInstanceMetaClass; /** @@ -36,35 +37,34 @@ public class GroovyProxyInterceptorLogic { public static final Object INVOKE_IMPLEMENTATION = new Object(); - public record InterceptorState( - String entityName, - Class<?> persistentClass, - Object identifier - ) {} + public record InterceptorState(String entityName, Class<?> persistentClass, Object identifier) {} public static Object handleUninitialized(InterceptorState state, String methodName, Object[] args) { - if ((methodName.equals("getMetaClass") || methodName.endsWith("getStaticMetaClass")) && (args == null || args.length == 0)) { + if (("getMetaClass".equals(methodName) || methodName.endsWith("getStaticMetaClass")) + && (args == null || args.length == 0)) { return InvokerHelper.getMetaClass(state.persistentClass()); } - if (methodName.equals("getProperty") && args.length == 1 && args[0].equals("id")) { + if ("getProperty".equals(methodName) && args.length == 1 && "id".equals(args[0])) { return state.identifier(); } - if (methodName.equals("ident") && (args == null || args.length == 0)) { + if ("ident".equals(methodName) && (args == null || args.length == 0)) { return state.identifier(); } - if ((methodName.equals("isDirty") || methodName.equals("hasChanged")) && (args == null || args.length == 0)) { + if (("isDirty".equals(methodName) || "hasChanged".equals(methodName)) && (args == null || args.length == 0)) { return false; } - if (methodName.equals("toString") && (args == null || args.length == 0)) { + if ("toString".equals(methodName) && (args == null || args.length == 0)) { return state.entityName() + ":" + state.identifier(); } return INVOKE_IMPLEMENTATION; } public static boolean isGroovyMethod(String methodName) { - return methodName.equals("getMetaClass") || methodName.equals("setMetaClass") || - methodName.equals("getProperty") || methodName.equals("setProperty") || - methodName.equals("invokeMethod"); + return "getMetaClass".equals(methodName) + || "setMetaClass".equals(methodName) + || "getProperty".equals(methodName) + || "setProperty".equals(methodName) + || "invokeMethod".equals(methodName); } public static ProxyInstanceMetaClass getProxyInstanceMetaClass(Object o) { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateAlias.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateAlias.java index ece144f317..bd3fac0f6d 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateAlias.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateAlias.java @@ -22,23 +22,9 @@ import org.grails.datastore.mapping.query.Query; /** * A internal criterion used to represent an alias for a basic collection join. - * + * * @author walterduquedeestrada */ -public class HibernateAlias implements Query.Criterion, Query.QueryElement { - private final String path; - private final String alias; - - public HibernateAlias(String path, String alias) { - this.path = path; - this.alias = alias; - } - - public String getPath() { - return path; - } +public record HibernateAlias(String path, String alias) implements Query.Criterion, Query.QueryElement { - public String getAlias() { - return alias; - } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java index b1f6d72859..e50a5c35f7 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java @@ -49,7 +49,7 @@ public record HqlQueryContext( String hql, Class<?> targetClass, Map<String, Object> namedParams, - Collection positionalParams, + Collection<?> positionalParams, Map<String, Object> querySettings, boolean isUpdate, boolean isNative) { @@ -65,13 +65,13 @@ public record HqlQueryContext( PersistentEntity entity, CharSequence queryCharseq, Map<?, ?> namedParams, - Collection positionalParams, - Map querySettings, + Collection<?> positionalParams, + Map<String, Object> querySettings, boolean isNative, boolean isUpdate) { Map<String, Object> _namedParams = namedParams != null ? new HashMap<>((Map<String, Object>) namedParams) : new HashMap<>(); - Collection positionalParamsCopy = positionalParams != null ? new ArrayList<>(positionalParams) : null; + Collection<Object> positionalParamsCopy = positionalParams != null ? new ArrayList<>(positionalParams) : null; Map<String, Object> querySettingsCopy = querySettings != null ? new HashMap<>(querySettings) : null; String hql; @@ -93,18 +93,18 @@ public record HqlQueryContext( public static @Nullable String resolveHql( CharSequence queryCharseq, boolean isNative, Map<String, Object> namedParams) { - String raw = queryCharseq instanceof GString gstr ? - buildNamedParameterQueryFromGString(gstr, namedParams) : - queryCharseq != null ? queryCharseq.toString() : ""; + String raw = queryCharseq instanceof GString gstr + ? buildNamedParameterQueryFromGString(gstr, namedParams) + : queryCharseq != null ? queryCharseq.toString() : ""; String normalized = normalizeMultiLineQueryString(raw); return isNative ? normalized : normalizeNonAliasedSelect(normalized); } public static @Nullable String resolveHql( - CharSequence queryCharseq, boolean isNative, Collection positionalParams) { - String raw = queryCharseq instanceof GString gstr ? - buildPositionalParameterQueryFromGString(gstr, positionalParams, isNative) : - queryCharseq != null ? queryCharseq.toString() : ""; + CharSequence queryCharseq, boolean isNative, Collection<Object> positionalParams) { + String raw = queryCharseq instanceof GString gstr + ? buildPositionalParameterQueryFromGString(gstr, positionalParams, isNative) + : queryCharseq != null ? queryCharseq.toString() : ""; String normalized = normalizeMultiLineQueryString(raw); return isNative ? normalized : normalizeNonAliasedSelect(normalized); } @@ -133,7 +133,7 @@ public record HqlQueryContext( * <p>Commas inside parentheses or string literals are ignored. */ static int countHqlProjections(CharSequence hql) { - if (hql == null || hql.length() == 0) return 0; + if (hql == null || hql.isEmpty()) return 0; String s = hql.toString().trim(); String lower = s.toLowerCase(Locale.ROOT); int selectIdx = lower.indexOf("select "); @@ -152,6 +152,11 @@ public record HqlQueryContext( sel = sel.substring("all ".length()).trim(); // Count top-level commas, ignoring those inside parens or string literals + int commas = getCommas(sel); + return commas == 0 ? 1 : 2; + } + + private static int getCommas(String sel) { int depth = 0, commas = 0; boolean inSingle = false, inDouble = false; for (int i = 0; i < sel.length(); i++) { @@ -170,7 +175,7 @@ public record HqlQueryContext( else if (c == ',' && depth == 0) commas++; } } - return commas == 0 ? 1 : 2; + return commas; } // ─── HQL normalization ──────────────────────────────────────────────────── @@ -217,8 +222,8 @@ public record HqlQueryContext( int tokenEnd = cur; while (tokenEnd < s.length() && !Character.isWhitespace(s.charAt(tokenEnd))) tokenEnd++; String token = s.substring(cur, tokenEnd).toLowerCase(Locale.ROOT); - boolean hasAlias = !token.isEmpty() && - !Set.of("where", "join", "left", "right", "inner", "outer", "group", "order", "having") + boolean hasAlias = !token.isEmpty() + && !Set.of("where", "join", "left", "right", "inner", "outer", "group", "order", "having") .contains(token); if (hasAlias) return s; @@ -269,7 +274,6 @@ public record HqlQueryContext( return query.trim().replace("\n", " "); } - @SuppressWarnings("unchecked") private static String buildNamedParameterQueryFromGString(GString query, Map<String, Object> params) { StringBuilder sql = new StringBuilder(); Object[] values = query.getValues(); @@ -285,9 +289,8 @@ public record HqlQueryContext( return sql.toString(); } - @SuppressWarnings("unchecked") private static String buildPositionalParameterQueryFromGString( - GString query, Collection positionalParams, boolean isNative) { + GString query, Collection<Object> positionalParams, boolean isNative) { StringBuilder sql = new StringBuilder(); Object[] values = query.getValues(); String[] strings = query.getStrings(); @@ -299,7 +302,8 @@ public record HqlQueryContext( } else { sql.append('?').append(positionalParams.size() + 1); } - positionalParams.add(values[i]); + Object value = values[i]; + positionalParams.add(value); } } return sql.toString(); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java index 3a23f6b1e8..7bc699eae9 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java @@ -95,7 +95,7 @@ public class JpaFromProvider implements Cloneable { // Also scan for HibernateAlias (basic collections) Map<String, String> basicAliasMap = new HashMap<>(); for (HibernateAlias ha : aliases) { - basicAliasMap.put(ha.getPath(), ha.getAlias()); + basicAliasMap.put(ha.path(), ha.alias()); } var definedAliases = detachedAssociationCriteriaList.stream() diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateDatastoreSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateDatastoreSpec.groovy index 6b320da48a..02b65e993a 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateDatastoreSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateDatastoreSpec.groovy @@ -18,22 +18,79 @@ */ package org.grails.orm.hibernate +import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.orm.hibernate.cfg.Settings -import spock.lang.Specification +import org.hibernate.FlushMode +import org.springframework.context.support.GenericApplicationContext -/** - * Created by graemerocher on 22/09/2016. - */ -class HibernateDatastoreSpec extends Specification { +class HibernateDatastoreSpec extends HibernateGormDatastoreSpec { + + void "test basic properties"() { + expect: + datastore.sessionFactory != null + datastore.dataSource != null + datastore.transactionManager != null + datastore.mappingContext != null + datastore.applicationEventPublisher != null + datastore.dataSourceName == 'default' + } + + void "test configuration settings"() { + expect: + !datastore.autoFlush // COMMIT mode in setupSpec + datastore.defaultFlushMode == FlushMode.COMMIT + !datastore.failOnError + datastore.cacheQueries + } + + void "test getDatastoreForConnection"() { + expect: + datastore.getDatastoreForConnection('dataSource') == datastore + datastore.getDatastoreForConnection('default') == datastore + datastore.getDatastoreForConnection('DEFAULT') == datastore + } + + void "test withFlushMode"() { + when: + boolean result = false + datastore.withFlushMode(FlushMode.ALWAYS) { + result = datastore.sessionFactory.currentSession.hibernateFlushMode == FlushMode.ALWAYS + return true + } - void "test configure via map"() { + then: + result + datastore.sessionFactory.currentSession.hibernateFlushMode == FlushMode.COMMIT + } + + void "test application context integration"() { + given: + def ctx = new GenericApplicationContext() + ctx.refresh() + + when: + datastore.setApplicationContext(ctx) + + then: + datastore.applicationContext == ctx + } + + void "test configure via map (Legacy/Test constructor)"() { when:"The map constructor is used" def config = Collections.singletonMap(Settings.SETTING_DB_CREATE, "create-drop") - HibernateDatastore datastore = new HibernateDatastore(config, Book) + HibernateDatastore testDatastore = new HibernateDatastore(config, GHUBook) then:"GORM is configured correctly" - Book.withNewSession { - Book.count() - } == 0 + testDatastore.getMappingContext().getPersistentEntity(GHUBook.name) != null + + cleanup: + testDatastore.close() } } + +@Entity +class GHUBook { + Long id + String title +} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy index 3567ac20f8..7cd4236721 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy @@ -26,6 +26,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersi import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentEntity import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher +import org.grails.datastore.mapping.core.connections.ConnectionSource class GrailsHibernatePersistentEntitySpec extends HibernateGormDatastoreSpec { @@ -155,7 +156,7 @@ class GrailsHibernatePersistentEntitySpec extends HibernateGormDatastoreSpec { GrailsHibernatePersistentEntity vehicle = getPersistentEntity(Vehicle) as GrailsHibernatePersistentEntity when: - def children = vehicle.getChildEntities("DEFAULT") + def children = vehicle.getChildEntities(ConnectionSource.DEFAULT) then: children.size() == 2 diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextSpec.groovy index a102789dd1..0dbd3bc783 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextSpec.groovy @@ -30,6 +30,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersi import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsJpaMappingConfigurationStrategy import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings import org.springframework.validation.Errors +import org.grails.datastore.mapping.core.connections.ConnectionSource class HibernateMappingContextSpec extends HibernateGormDatastoreSpec { @@ -120,11 +121,11 @@ class HibernateMappingContextSpec extends HibernateGormDatastoreSpec { void "getHibernatePersistentEntities returns GrailsHibernatePersistentEntity instances"() { when: - def entities = mappingContext.getHibernatePersistentEntities("DEFAULT") + def entities = mappingContext.getHibernatePersistentEntities(ConnectionSource.DEFAULT) then: entities.every { it instanceof GrailsHibernatePersistentEntity } - entities.every { it.dataSourceName == "DEFAULT" } + entities.every { it.dataSourceName == ConnectionSource.DEFAULT } } void "getHibernatePersistentEntities sets the dataSourceName on each entity"() { diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy index 10e34481b3..4ae93f37cb 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy @@ -27,6 +27,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentE import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder import org.hibernate.boot.spi.MetadataBuildingContext import org.hibernate.mapping.RootClass +import org.grails.datastore.mapping.core.connections.ConnectionSource class RootBinderSpec extends HibernateGormDatastoreSpec { @@ -53,7 +54,7 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { discriminatorPropertyBinder = Mock(DiscriminatorPropertyBinder) binder = new RootBinder( - "default", + ConnectionSource.DEFAULT, multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, @@ -67,7 +68,7 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { given: def entity = Mock(HibernatePersistentEntity) entity.getName() >> "Parent" - entity.getChildEntities("default") >> [] + entity.getChildEntities(ConnectionSource.DEFAULT) >> [] entity.getMappedForm() >> new Mapping() def mappings = sharedCollector @@ -91,7 +92,7 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { def entity = Mock(HibernatePersistentEntity) def childEntity = Mock(HibernatePersistentEntity) entity.getName() >> "Parent" - entity.getChildEntities("default") >> [childEntity] + entity.getChildEntities(ConnectionSource.DEFAULT) >> [childEntity] def mapping = new Mapping() mapping.setTablePerHierarchy(true) entity.getMappedForm() >> mapping diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy index 3e0e0c69e6..30d3aacec2 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy @@ -22,12 +22,12 @@ package org.grails.orm.hibernate.cfg.domainbinding.binder import org.hibernate.mapping.SingleTableSubclass import grails.gorm.specs.HibernateGormDatastoreSpec -import org.grails.orm.hibernate.cfg.Mapping import org.grails.orm.hibernate.cfg.MappingCacheHolder import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentEntity import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder import org.hibernate.boot.spi.MetadataBuildingContext import org.hibernate.mapping.RootClass +import org.grails.datastore.mapping.core.connections.ConnectionSource class SubClassBinderSpec extends HibernateGormDatastoreSpec { @@ -48,7 +48,7 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { binder = new SubClassBinder( subclassMappingBinder, multiTenantFilterBinder, - "default" + ConnectionSource.DEFAULT, ) } @@ -56,7 +56,7 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { given: def subEntity = Mock(HibernatePersistentEntity) subEntity.getName() >> "Child" - subEntity.getChildEntities("default") >> [] + subEntity.getChildEntities(ConnectionSource.DEFAULT) >> [] def rootClass = new RootClass(metadataBuildingContext) rootClass.setEntityName("Parent") rootClass.setJpaEntityName("Parent") @@ -79,8 +79,8 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { def grandChildEntity = Mock(HibernatePersistentEntity) subEntity.getName() >> "Child" grandChildEntity.getName() >> "GrandChild" - subEntity.getChildEntities("default") >> [grandChildEntity] - grandChildEntity.getChildEntities("default") >> [] + subEntity.getChildEntities(ConnectionSource.DEFAULT) >> [grandChildEntity] + grandChildEntity.getChildEntities(ConnectionSource.DEFAULT) >> [] def rootClass = new RootClass(metadataBuildingContext) rootClass.setEntityName("Parent") diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java index 8e1614f6cd..ac42ac79aa 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java @@ -31,7 +31,14 @@ public interface ConnectionSource<T, S extends ConnectionSourceSettings> extends /** * The name of the default connection source */ - String DEFAULT = "DEFAULT"; + String DEFAULT = "default"; + + /** + * The name of the default connection source used in previous versions of GORM + * @deprecated Use {@link #DEFAULT} instead + */ + @Deprecated + String OLD_DEFAULT = "DEFAULT"; /** * Constance for a mapping to all connection sources diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java index d65f463061..9300985ec7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java @@ -236,7 +236,7 @@ public interface MappingContext { */ void addMappingContextListener(Listener listener); - PersistentEntity createEmbeddedEntity(Class type); + PersistentEntity createEmbeddedEntity(Class<?> type); /** * Obtains a {@link EntityReflector} instance for the given entity
