From 14b35bb3b6b6e66b9aa52da4439afebee2b7475a Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 20 Apr 2021 13:11:26 +0200 Subject: [PATCH 01/45] HHH-14273 Support for jakarta.persistence prefixed String properties --- .../org/hibernate/annotations/QueryHints.java | 5 + .../boot/internal/ClassLoaderAccessImpl.java | 1 + .../boot/internal/MetadataBuilderImpl.java | 21 +- .../SessionFactoryOptionsBuilder.java | 10 +- .../org/hibernate/cfg/AvailableSettings.java | 345 ++++++++++++++++++ .../cfg/annotations/QueryHintDefinition.java | 9 +- .../engine/spi/EffectiveEntityGraph.java | 10 +- .../org/hibernate/graph/GraphSemantic.java | 16 +- .../internal/FastSessionServices.java | 27 +- .../internal/SessionFactoryImpl.java | 9 +- .../org/hibernate/internal/SessionImpl.java | 46 ++- .../java/org/hibernate/jpa/QueryHints.java | 25 ++ .../EntityManagerFactoryBuilderImpl.java | 148 +++++++- .../boot/internal/PersistenceXmlParser.java | 13 + .../org/hibernate/jpa/boot/spi/Bootstrap.java | 1 - .../jpa/boot/spi/ProviderChecker.java | 6 +- .../jpa/internal/util/LockOptionsHelper.java | 20 +- .../query/internal/AbstractProducedQuery.java | 25 +- .../spi/ManagedBeanRegistryInitiator.java | 5 +- .../tool/schema/internal/Helper.java | 18 +- .../HibernateSchemaManagementTool.java | 25 +- .../schema/internal/SchemaCreatorImpl.java | 6 +- .../spi/SchemaManagementToolCoordinator.java | 62 +++- 23 files changed, 792 insertions(+), 61 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java b/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java index 7bfd3ec012..dfb436ed68 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java @@ -96,6 +96,11 @@ public class QueryHints { */ public static final String TIMEOUT_JPA = "javax.persistence.query.timeout"; + /** + * Apply a JPA query timeout, which is defined in milliseconds. + */ + public static final String TIMEOUT_JAKARTA_JPA = "jakarta.persistence.query.timeout"; + /** * Available to apply lock mode to a native SQL query since JPA requires that * {@link javax.persistence.Query#setLockMode} throw an IllegalStateException if called for a native query. diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java index 6797a0298c..0234da6193 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java @@ -85,6 +85,7 @@ public class ClassLoaderAccessImpl implements ClassLoaderAccess { // classes in any of these packages are safe to load through the "live" ClassLoader return name.startsWith( "java." ) || name.startsWith( "javax." ) + || name.startsWith( "jakarta." ) || name.startsWith( "org.hibernate." ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java index 5c96508086..61f98f680e 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java @@ -659,7 +659,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont ); this.sharedCacheMode = configService.getSetting( - "javax.persistence.sharedCache.mode", + AvailableSettings.JPA_SHARED_CACHE_MODE, new ConfigurationService.Converter() { @Override public SharedCacheMode convert(Object value) { @@ -674,7 +674,24 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont return SharedCacheMode.valueOf( value.toString() ); } }, - SharedCacheMode.UNSPECIFIED + configService.getSetting( + AvailableSettings.JAKARTA_JPA_SHARED_CACHE_MODE, + new ConfigurationService.Converter() { + @Override + public SharedCacheMode convert(Object value) { + if ( value == null ) { + return null; + } + + if ( SharedCacheMode.class.isInstance( value ) ) { + return (SharedCacheMode) value; + } + + return SharedCacheMode.valueOf( value.toString() ); + } + }, + SharedCacheMode.UNSPECIFIED + ) ); this.defaultCacheAccessType = configService.getSetting( diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java index 364ccd6fc3..7ddff3bf79 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java @@ -272,8 +272,14 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { ( (ConfigurationServiceImpl) cfgService ).injectServices( (ServiceRegistryImplementor) serviceRegistry ); } - this.beanManagerReference = configurationSettings.get( "javax.persistence.bean.manager" ); - this.validatorFactoryReference = configurationSettings.get( "javax.persistence.validation.factory" ); + this.beanManagerReference = configurationSettings.getOrDefault( + AvailableSettings.CDI_BEAN_MANAGER, + configurationSettings.get( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER ) + ); + this.validatorFactoryReference = configurationSettings.getOrDefault( + AvailableSettings.JPA_VALIDATION_FACTORY, + configurationSettings.get( AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) + ); this.sessionFactoryName = (String) configurationSettings.get( SESSION_FACTORY_NAME ); this.sessionFactoryNameAlsoJndiName = cfgService.getSetting( diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 65ef3f9afa..88338b5d0f 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -208,6 +208,185 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { String CDI_BEAN_MANAGER = "javax.persistence.bean.manager"; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Jakarta JPA defined settings + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * The name of the {@link javax.persistence.spi.PersistenceProvider} implementor + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.4 + */ + String JAKARTA_JPA_PERSISTENCE_PROVIDER = "jakarta.persistence.provider"; + + /** + * The type of transactions supported by the entity managers. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.2 + */ + String JAKARTA_JPA_TRANSACTION_TYPE = "jakarta.persistence.transactionType"; + + /** + * The JNDI name of a JTA {@link javax.sql.DataSource}. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.5 + */ + String JAKARTA_JPA_JTA_DATASOURCE = "jakarta.persistence.jtaDataSource"; + + /** + * The JNDI name of a non-JTA {@link javax.sql.DataSource}. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.5 + */ + String JAKARTA_JPA_NON_JTA_DATASOURCE = "jakarta.persistence.nonJtaDataSource"; + + /** + * The name of a JDBC driver to use to connect to the database. + *

+ * Used in conjunction with {@link #JPA_JDBC_URL}, {@link #JPA_JDBC_USER} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_DRIVER = "jakarta.persistence.jdbc.driver"; + + /** + * The JDBC connection url to use to connect to the database. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_USER} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_URL = "jakarta.persistence.jdbc.url"; + + /** + * The JDBC connection user name. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_URL} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_USER = "jakarta.persistence.jdbc.user"; + + /** + * The JDBC connection password. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_URL} and {@link #JPA_JDBC_USER} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_PASSWORD = "jakarta.persistence.jdbc.password"; + + /** + * Used to indicate whether second-level (what JPA terms shared cache) caching is + * enabled as per the rules defined in JPA 2 section 3.1.7. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.7 + * @see javax.persistence.SharedCacheMode + */ + String JAKARTA_JPA_SHARED_CACHE_MODE = "jakarta.persistence.sharedCache.mode"; + + /** + * NOTE : Not a valid EMF property... + *

+ * Used to indicate if the provider should attempt to retrieve requested data + * in the shared cache. + * + * @see javax.persistence.CacheRetrieveMode + */ + String JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ="jakarta.persistence.cache.retrieveMode"; + + /** + * NOTE : Not a valid EMF property... + *

+ * Used to indicate if the provider should attempt to store data loaded from the database + * in the shared cache. + * + * @see javax.persistence.CacheStoreMode + */ + String JAKARTA_JPA_SHARED_CACHE_STORE_MODE ="jakarta.persistence.cache.storeMode"; + + /** + * Used to indicate what form of automatic validation is in effect as per rules defined + * in JPA 2 section 3.6.1.1 + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.8 + * @see javax.persistence.ValidationMode + */ + String JAKARTA_JPA_VALIDATION_MODE = "jakarta.persistence.validation.mode"; + + /** + * Used to pass along any discovered validator factory. + */ + String JAKARTA_JPA_VALIDATION_FACTORY = "jakarta.persistence.validation.factory"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_PERSIST_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-persist"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_UPDATE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-update"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_REMOVE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-remove"; + + /** + * Used to request (hint) a pessimistic lock scope. + *

+ * See JPA 2 sections 8.2.1.9 and 3.4.4.3 + */ + String JAKARTA_JPA_LOCK_SCOPE = "jakarta.persistence.lock.scope"; + + /** + * Used to request (hint) a pessimistic lock timeout (in milliseconds). + *

+ * See JPA 2 sections 8.2.1.9 and 3.4.4.3 + */ + String JAKARTA_JPA_LOCK_TIMEOUT = "jakarta.persistence.lock.timeout"; + + /** + * Used to pass along the CDI BeanManager, if any, to be used. + * + * According to JPA, strictly, the BeanManager should be passed in + * at boot-time and be ready for use at that time. However not all + * environments can do this (WildFly e.g.). To accommodate such + * environments, Hibernate provides 2 options: + * + * * a proprietary CDI extension SPI (that we have proposed to + * the CDI spec group as a standard option) that can be used + * to provide delayed BeanManager access. To use this solution, + * the reference passed as the BeanManager during bootstrap + * should be typed as {@link ExtendedBeanManager} + * * delayed access to the BeanManager reference. Here, Hibernate + * will not access the reference passed as the BeanManager during + * bootstrap until it is first needed. Note however that this has + * the effect of delaying any deployment problems until after + * bootstrapping. + * + * This setting is used to configure Hibernate ORM's access to + * the BeanManager (either directly or via {@link ExtendedBeanManager}). + */ + String JAKARTA_CDI_BEAN_MANAGER = "jakarta.persistence.bean.manager"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BootstrapServiceRegistry level settings // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1486,6 +1665,172 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { */ String HBM2DDL_CREATE_SCHEMAS = "javax.persistence.create-database-schemas"; + /** + * Setting to perform SchemaManagementTool actions against the database directly via JDBC + * automatically as part of the SessionFactory lifecycle. Valid options are defined by the + * {@link org.hibernate.tool.schema.Action} enum. + *

+ * Interpreted in combination with {@link #HBM2DDL_AUTO}. If no value is specified, the default + * is "none" ({@link org.hibernate.tool.schema.Action#NONE}). + * + * @see org.hibernate.tool.schema.Action + */ + String JAKARTA_HBM2DDL_DATABASE_ACTION = "jakarta.persistence.schema-generation.database.action"; + + /** + * Setting to perform SchemaManagementTool actions writing the commands into a DDL script file. + * Valid options are defined by the {@link org.hibernate.tool.schema.Action} enum. + *

+ * Interpreted in combination with {@link #HBM2DDL_AUTO}. If no value is specified, the default + * is "none" ({@link org.hibernate.tool.schema.Action#NONE}). + * + * @see org.hibernate.tool.schema.Action + */ + String JAKARTA_HBM2DDL_SCRIPTS_ACTION = "jakarta.persistence.schema-generation.scripts.action"; + + /** + * Allows passing a specific {@link java.sql.Connection} instance to be used by SchemaManagementTool. + *

+ * May also be used to determine the values for {@value #HBM2DDL_DB_NAME}, + * {@value #HBM2DDL_DB_MAJOR_VERSION} and {@value #HBM2DDL_DB_MINOR_VERSION}. + */ + String JAKARTA_HBM2DDL_CONNECTION = "jakarta.persistence.schema-generation-connection"; + + /** + * Specifies the name of the database provider in cases where a Connection to the underlying database is + * not available (aka, mainly in generating scripts). In such cases, a value for this setting + * *must* be specified. + *

+ * The value of this setting is expected to match the value returned by + * {@link java.sql.DatabaseMetaData#getDatabaseProductName()} for the target database. + *

+ * Additionally specifying {@value #HBM2DDL_DB_MAJOR_VERSION} and/or {@value #HBM2DDL_DB_MINOR_VERSION} + * may be required to understand exactly how to generate the required schema commands. + * + * @see #HBM2DDL_DB_MAJOR_VERSION + * @see #HBM2DDL_DB_MINOR_VERSION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_DB_NAME = "jakarta.persistence.database-product-name"; + + /** + * Specifies the major version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion} for the target database. This value is used to + * help more precisely determine how to perform schema generation tasks for the underlying database in cases + * where {@value #HBM2DDL_DB_NAME} does not provide enough distinction. + + * @see #HBM2DDL_DB_NAME + * @see #HBM2DDL_DB_MINOR_VERSION + */ + String JAKARTA_HBM2DDL_DB_MAJOR_VERSION = "jakarta.persistence.database-major-version"; + + /** + * Specifies the minor version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion} for the target database. This value is used to + * help more precisely determine how to perform schema generation tasks for the underlying database in cases + * where the combination of {@value #HBM2DDL_DB_NAME} and {@value #HBM2DDL_DB_MAJOR_VERSION} does not provide + * enough distinction. + * + * @see #HBM2DDL_DB_NAME + * @see #HBM2DDL_DB_MAJOR_VERSION + */ + String JAKARTA_HBM2DDL_DB_MINOR_VERSION = "jakarta.persistence.database-minor-version"; + + /** + * Specifies whether schema generation commands for schema creation are to be determined based on object/relational + * mapping metadata, DDL scripts, or a combination of the two. See {@link SourceType} for valid set of values. + * If no value is specified, a default is assumed as follows:

    + *
  • + * if source scripts are specified (per {@value #HBM2DDL_CREATE_SCRIPT_SOURCE}),then "scripts" is assumed + *
  • + *
  • + * otherwise, "metadata" is assumed + *
  • + *
+ * + * @see SourceType + */ + String JAKARTA_HBM2DDL_CREATE_SOURCE = "jakarta.persistence.schema-generation.create-source"; + + /** + * Specifies whether schema generation commands for schema dropping are to be determined based on object/relational + * mapping metadata, DDL scripts, or a combination of the two. See {@link SourceType} for valid set of values. + * If no value is specified, a default is assumed as follows:
    + *
  • + * if source scripts are specified (per {@value #HBM2DDL_DROP_SCRIPT_SOURCE}),then "scripts" is assumed + *
  • + *
  • + * otherwise, "metadata" is assumed + *
  • + *
+ * + * @see SourceType + */ + String JAKARTA_HBM2DDL_DROP_SOURCE = "jakarta.persistence.schema-generation.drop-source"; + + /** + * Specifies the CREATE script file as either a {@link java.io.Reader} configured for reading of the DDL script + * file or a string designating a file {@link java.net.URL} for the DDL script. + *

+ * Hibernate historically also accepted {@link #HBM2DDL_IMPORT_FILES} for a similar purpose. This setting + * should be preferred over {@link #HBM2DDL_IMPORT_FILES} moving forward + * + * @see #HBM2DDL_CREATE_SOURCE + * @see #HBM2DDL_IMPORT_FILES + */ + String JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.create-script-source"; + + /** + * Specifies the DROP script file as either a {@link java.io.Reader} configured for reading of the DDL script + * file or a string designating a file {@link java.net.URL} for the DDL script. + * + * @see #HBM2DDL_DROP_SOURCE + */ + String JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.drop-script-source"; + + /** + * For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema creation commands should + * be written to DDL script file, {@value #HBM2DDL_SCRIPTS_CREATE_TARGET} specifies either a + * {@link java.io.Writer} configured for output of the DDL script or a string specifying the file URL for the DDL + * script. + * + * @see #HBM2DDL_SCRIPTS_ACTION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET = "jakarta.persistence.schema-generation.scripts.create-target"; + + /** + * For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema drop commands should + * be written to DDL script file, {@value #HBM2DDL_SCRIPTS_DROP_TARGET} specifies either a + * {@link java.io.Writer} configured for output of the DDL script or a string specifying the file URL for the DDL + * script. + * + * @see #HBM2DDL_SCRIPTS_ACTION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET = "jakarta.persistence.schema-generation.scripts.drop-target"; + + /** + * JPA variant of {@link #HBM2DDL_IMPORT_FILES} + *

+ * Specifies a {@link java.io.Reader} configured for reading of the SQL load script or a string designating the + * file {@link java.net.URL} for the SQL load script. + *

+ * A "SQL load script" is a script that performs some database initialization (INSERT, etc). + */ + String JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE = "jakarta.persistence.sql-load-script-source"; + + /** + * The JPA variant of {@link #HBM2DDL_CREATE_NAMESPACES} + *

+ * Specifies whether the persistence provider is to create the database schema(s) in addition to creating + * database objects (tables, sequences, constraints, etc). The value of this boolean property should be set + * to {@code true} if the persistence provider is to create schemas in the database or to generate DDL that + * contains "CREATE SCHEMA" commands. If this property is not supplied (or is explicitly {@code false}), the + * provider should not attempt to create database schemas. + */ + String JAKARTA_HBM2DDL_CREATE_SCHEMAS = "jakarta.persistence.create-database-schemas"; + /** * @deprecated Use {@link #HBM2DDL_CREATE_SCHEMAS} instead: this variable name had a typo. */ diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java index de61781476..da782f082d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java @@ -21,6 +21,7 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.annotations.QueryHints; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.util.LockModeConverter; /** @@ -128,6 +129,9 @@ public class QueryHintDefinition { public Integer getTimeout(String queryName) { Integer timeout = getInteger( queryName, QueryHints.TIMEOUT_JPA ); + if ( timeout == null ) { + timeout = getInteger( queryName, QueryHints.TIMEOUT_JAKARTA_JPA ); + } if ( timeout != null ) { // convert milliseconds to seconds @@ -142,7 +146,10 @@ public class QueryHintDefinition { public LockOptions determineLockOptions(NamedQuery namedQueryAnnotation) { LockModeType lockModeType = namedQueryAnnotation.lockMode(); - Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout" ); + Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), AvailableSettings.JPA_LOCK_TIMEOUT ); + if ( lockTimeoutHint == null ) { + lockTimeoutHint = getInteger( namedQueryAnnotation.name(), AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT ); + } Boolean followOnLocking = getBoolean( namedQueryAnnotation.name(), QueryHints.FOLLOW_ON_LOCKING ); return determineLockOptions(lockModeType, lockTimeoutHint, followOnLocking); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java index fa96dc082a..bb07a15e3e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java @@ -113,8 +113,14 @@ public class EffectiveEntityGraph implements AppliedGraph, Serializable { return; } - final RootGraphImplementor fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJpaHintName() ); - final RootGraphImplementor loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJpaHintName() ); + RootGraphImplementor fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJpaHintName() ); + RootGraphImplementor loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJpaHintName() ); + if (fetchHint == null) { + fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJakartaJpaHintName() ); + } + if (loadHint == null) { + loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJakartaJpaHintName() ); + } if ( fetchHint == null && loadHint == null ) { log.debugf( "Neither LOAD nor FETCH graph were found in properties" ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java b/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java index 12498834e7..ceb0817234 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java @@ -19,7 +19,7 @@ public enum GraphSemantic { * subsequent select). Attributes that are not specified are treated as * FetchType.LAZY invariably. */ - FETCH( "javax.persistence.fetchgraph" ), + FETCH( "javax.persistence.fetchgraph", "jakarta.persistence.fetchgraph" ), /** * Indicates a "load graph" EntityGraph. Attributes explicitly specified @@ -28,26 +28,32 @@ public enum GraphSemantic { * FetchType.LAZY or FetchType.EAGER depending on the attribute's definition * in metadata. */ - LOAD( "javax.persistence.loadgraph" ); + LOAD( "javax.persistence.loadgraph", "jakarta.persistence.loadgraph" ); private final String jpaHintName; + private final String jakartaJpaHintName; - GraphSemantic(String jpaHintName) { + GraphSemantic(String jpaHintName, String jakartaJpaHintName) { this.jpaHintName = jpaHintName; + this.jakartaJpaHintName = jakartaJpaHintName; } public String getJpaHintName() { return jpaHintName; } + public String getJakartaJpaHintName() { + return jakartaJpaHintName; + } + public static GraphSemantic fromJpaHintName(String hintName) { assert hintName != null; - if ( FETCH.getJpaHintName().equals( hintName ) ) { + if ( FETCH.getJpaHintName().equals( hintName ) || FETCH.getJakartaJpaHintName().equals( hintName ) ) { return FETCH; } - if ( LOAD.getJpaHintName().equalsIgnoreCase( hintName ) ) { + if ( LOAD.getJpaHintName().equalsIgnoreCase( hintName ) || LOAD.getJakartaJpaHintName().equalsIgnoreCase( hintName ) ) { return LOAD; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java index 8f04bcb53e..a8fac37fe3 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java @@ -71,6 +71,10 @@ import javax.persistence.CacheRetrieveMode; import javax.persistence.CacheStoreMode; import javax.persistence.PessimisticLockScope; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -277,18 +281,27 @@ public final class FastSessionServices { //Static defaults: p.putIfAbsent( AvailableSettings.FLUSH_MODE, FlushMode.AUTO.name() ); p.putIfAbsent( JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); + p.putIfAbsent( JAKARTA_JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); p.putIfAbsent( JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); + p.putIfAbsent( JAKARTA_JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); p.putIfAbsent( JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); + p.putIfAbsent( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); p.putIfAbsent( JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); + p.putIfAbsent( JAKARTA_JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); //Defaults defined by SessionFactory configuration: final String[] ENTITY_MANAGER_SPECIFIC_PROPERTIES = { JPA_LOCK_SCOPE, + JAKARTA_JPA_LOCK_SCOPE, JPA_LOCK_TIMEOUT, + JAKARTA_JPA_LOCK_TIMEOUT, AvailableSettings.FLUSH_MODE, JPA_SHARED_CACHE_RETRIEVE_MODE, + JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, JPA_SHARED_CACHE_STORE_MODE, - QueryHints.SPEC_HINT_TIMEOUT + JAKARTA_JPA_SHARED_CACHE_STORE_MODE, + QueryHints.SPEC_HINT_TIMEOUT, + QueryHints.JAKARTA_SPEC_HINT_TIMEOUT }; final Map properties = sf.getProperties(); for ( String key : ENTITY_MANAGER_SPECIFIC_PROPERTIES ) { @@ -328,11 +341,19 @@ public final class FastSessionServices { } private static CacheRetrieveMode determineCacheRetrieveMode(Map settings) { - return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + if ( cacheRetrieveMode == null ) { + return (CacheRetrieveMode) settings.get( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ); + } + return cacheRetrieveMode; } private static CacheStoreMode determineCacheStoreMode(Map settings) { - return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + if ( cacheStoreMode == null ) { + return ( CacheStoreMode ) settings.get( JAKARTA_JPA_SHARED_CACHE_STORE_MODE ); + } + return cacheStoreMode; } public ConnectionObserverStatsBridge getDefaultJdbcObserver() { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index d2a00b82ed..2c8bf16f09 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -234,12 +234,17 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { this.properties = new HashMap<>(); this.properties.putAll( serviceRegistry.getService( ConfigurationService.class ).getSettings() ); - if ( !properties.containsKey( AvailableSettings.JPA_VALIDATION_FACTORY ) ) { + if ( !properties.containsKey( AvailableSettings.JPA_VALIDATION_FACTORY ) + && !properties.containsKey( AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) ) { if ( getSessionFactoryOptions().getValidatorFactoryReference() != null ) { properties.put( AvailableSettings.JPA_VALIDATION_FACTORY, getSessionFactoryOptions().getValidatorFactoryReference() ); + properties.put( + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + getSessionFactoryOptions().getValidatorFactoryReference() + ); } } @@ -1647,6 +1652,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { private void maskOutSensitiveInformation(Map props) { maskOutIfSet( props, AvailableSettings.JPA_JDBC_USER ); maskOutIfSet( props, AvailableSettings.JPA_JDBC_PASSWORD ); + maskOutIfSet( props, AvailableSettings.JAKARTA_JPA_JDBC_USER ); + maskOutIfSet( props, AvailableSettings.JAKARTA_JPA_JDBC_PASSWORD ); maskOutIfSet( props, AvailableSettings.USER ); maskOutIfSet( props, AvailableSettings.PASS ); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 6cef2427fa..e54aabe092 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -175,6 +175,10 @@ import org.hibernate.stat.SessionStatistics; import org.hibernate.stat.internal.SessionStatisticsImpl; import org.hibernate.stat.spi.StatisticsImplementor; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -305,8 +309,28 @@ public class SessionImpl if ( ( queryTimeout = getSessionProperty( QueryHints.SPEC_HINT_TIMEOUT ) ) != null ) { query.setHint( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout ); } + final Object jakartaQueryTimeout; + if ( ( jakartaQueryTimeout = getSessionProperty( QueryHints.JAKARTA_SPEC_HINT_TIMEOUT ) ) != null ) { + query.setHint( QueryHints.JAKARTA_SPEC_HINT_TIMEOUT, jakartaQueryTimeout ); + } final Object lockTimeout; - if ( ( lockTimeout = getSessionProperty( JPA_LOCK_TIMEOUT ) ) != null ) { + final Object jpaLockTimeout = getSessionProperty( JPA_LOCK_TIMEOUT ); + if ( jpaLockTimeout == null ) { + lockTimeout = getSessionProperty( JAKARTA_JPA_LOCK_TIMEOUT ); + } + else if ( Integer.valueOf( LockOptions.WAIT_FOREVER ).equals( jpaLockTimeout ) ) { + final Object jakartaLockTimeout = getSessionProperty( JAKARTA_JPA_LOCK_TIMEOUT ); + if ( jakartaLockTimeout == null ) { + lockTimeout = jpaLockTimeout; + } + else { + lockTimeout = jakartaLockTimeout; + } + } + else { + lockTimeout = jpaLockTimeout; + } + if ( lockTimeout != null ) { query.setHint( JPA_LOCK_TIMEOUT, lockTimeout ); } } @@ -3424,11 +3448,19 @@ public class SessionImpl } private static CacheRetrieveMode determineCacheRetrieveMode(Map settings) { - return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + if ( cacheRetrieveMode == null ) { + return (CacheRetrieveMode) settings.get( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ); + } + return cacheRetrieveMode; } private static CacheStoreMode determineCacheStoreMode(Map settings) { - return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + if ( cacheStoreMode == null ) { + return ( CacheStoreMode ) settings.get( JAKARTA_JPA_SHARED_CACHE_STORE_MODE ); + } + return cacheStoreMode; } private void checkTransactionNeededForUpdateOperation() { @@ -3574,10 +3606,14 @@ public class SessionImpl if ( AvailableSettings.FLUSH_MODE.equals( propertyName ) ) { setHibernateFlushMode( ConfigurationHelper.getFlushMode( value, FlushMode.AUTO ) ); } - else if ( JPA_LOCK_SCOPE.equals( propertyName ) || JPA_LOCK_TIMEOUT.equals( propertyName ) ) { + else if ( JPA_LOCK_SCOPE.equals( propertyName ) || JPA_LOCK_TIMEOUT.equals( propertyName ) + || JAKARTA_JPA_LOCK_SCOPE.equals( propertyName ) || JAKARTA_JPA_LOCK_TIMEOUT.equals( propertyName ) ) { LockOptionsHelper.applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite ); } - else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) || JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) ) { + else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) + || JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) + || JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) + || JAKARTA_JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) ) { getSession().setCacheMode( CacheModeHelper.interpretCacheMode( determineCacheStoreMode( properties ), diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java b/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java index b71d4cdf35..47c42a7a4f 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java @@ -23,6 +23,7 @@ import static org.hibernate.annotations.QueryHints.NATIVE_SPACES; import static org.hibernate.annotations.QueryHints.PASS_DISTINCT_THROUGH; import static org.hibernate.annotations.QueryHints.READ_ONLY; import static org.hibernate.annotations.QueryHints.TIMEOUT_HIBERNATE; +import static org.hibernate.annotations.QueryHints.TIMEOUT_JAKARTA_JPA; import static org.hibernate.annotations.QueryHints.TIMEOUT_JPA; /** @@ -42,6 +43,11 @@ public class QueryHints { */ public static final String SPEC_HINT_TIMEOUT = TIMEOUT_JPA; + /** + * The hint key for specifying a query timeout per JPA, which defines the timeout in milliseconds + */ + public static final String JAKARTA_SPEC_HINT_TIMEOUT = TIMEOUT_JAKARTA_JPA; + /** * The hint key for specifying a comment which is to be embedded into the SQL sent to the database. */ @@ -100,6 +106,22 @@ public class QueryHints { */ public static final String HINT_LOADGRAPH = GraphSemantic.LOAD.getJpaHintName(); + /** + * Hint providing a "fetchgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as + * FetchType.EAGER (via join fetch or subsequent select). + * + * Note: Currently, attributes that are not specified are treated as FetchType.LAZY or FetchType.EAGER depending + * on the attribute's definition in metadata, rather than forcing FetchType.LAZY. + */ + public static final String JAKARTA_HINT_FETCHGRAPH = GraphSemantic.FETCH.getJakartaJpaHintName(); + + /** + * Hint providing a "loadgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as + * FetchType.EAGER (via join fetch or subsequent select). Attributes that are not specified are treated as + * FetchType.LAZY or FetchType.EAGER depending on the attribute's definition in metadata + */ + public static final String JAKARTA_HINT_LOADGRAPH = GraphSemantic.LOAD.getJakartaJpaHintName(); + public static final String HINT_FOLLOW_ON_LOCKING = FOLLOW_ON_LOCKING; public static final String HINT_PASS_DISTINCT_THROUGH = PASS_DISTINCT_THROUGH; @@ -113,6 +135,7 @@ public class QueryHints { HashSet hints = new HashSet<>(); hints.add( HINT_TIMEOUT ); hints.add( SPEC_HINT_TIMEOUT ); + hints.add( JAKARTA_SPEC_HINT_TIMEOUT ); hints.add( HINT_COMMENT ); hints.add( HINT_FETCH_SIZE ); hints.add( HINT_CACHE_REGION ); @@ -123,6 +146,8 @@ public class QueryHints { hints.add( HINT_NATIVE_LOCKMODE ); hints.add( HINT_FETCHGRAPH ); hints.add( HINT_LOADGRAPH ); + hints.add( JAKARTA_HINT_FETCHGRAPH ); + hints.add( JAKARTA_HINT_LOADGRAPH ); hints.add( HINT_NATIVE_SPACES ); return java.util.Collections.unmodifiableSet( hints ); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index 3894e2c358..8d0adeea1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -91,6 +91,15 @@ import static org.hibernate.cfg.AvailableSettings.DRIVER; import static org.hibernate.cfg.AvailableSettings.JACC_CONTEXT_ID; import static org.hibernate.cfg.AvailableSettings.JACC_ENABLED; import static org.hibernate.cfg.AvailableSettings.JACC_PREFIX; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_DRIVER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_PASSWORD; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_URL; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_USER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_VALIDATION_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_DRIVER; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_PASSWORD; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_URL; @@ -259,7 +268,13 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil metamodelBuilder.getBootstrapContext() ); - withValidatorFactory( configurationValues.get( org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY ) ); + final Object validatorFactory = configurationValues.get( org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY ); + if ( validatorFactory == null ) { + withValidatorFactory( configurationValues.get( org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) ); + } + else { + withValidatorFactory( validatorFactory ); + } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // push back class transformation to the environment; for the time being this only has any effect in EE @@ -572,20 +587,30 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // normalize ValidationMode final Object intgValidationMode = integrationSettingsCopy.remove( JPA_VALIDATION_MODE ); + final Object jakartaIntgValidationMode = integrationSettingsCopy.remove( JAKARTA_JPA_VALIDATION_MODE ); if ( intgValidationMode != null ) { mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, intgValidationMode ); } + else if ( jakartaIntgValidationMode != null ) { + mergedSettings.configurationValues.put( JAKARTA_JPA_VALIDATION_MODE, jakartaIntgValidationMode ); + } else if ( persistenceUnit.getValidationMode() != null ) { mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() ); + mergedSettings.configurationValues.put( JAKARTA_JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() ); } // normalize SharedCacheMode final Object intgCacheMode = integrationSettingsCopy.remove( JPA_SHARED_CACHE_MODE ); + final Object jakartaIntgCacheMode = integrationSettingsCopy.remove( JAKARTA_JPA_SHARED_CACHE_MODE ); if ( intgCacheMode != null ) { mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, intgCacheMode ); } + else if ( jakartaIntgCacheMode != null ) { + mergedSettings.configurationValues.put( JAKARTA_JPA_SHARED_CACHE_MODE, jakartaIntgCacheMode ); + } else if ( persistenceUnit.getSharedCacheMode() != null ) { mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); + mergedSettings.configurationValues.put( JAKARTA_JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); } // Apply all "integration overrides" as the last step. By specification, @@ -618,16 +643,20 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil final Object effectiveUser = NullnessHelper.coalesceSuppliedValues( () -> integrationSettingsCopy.remove( USER ), () -> integrationSettingsCopy.remove( JPA_JDBC_USER ), + () -> integrationSettingsCopy.remove( JAKARTA_JPA_JDBC_USER ), () -> extractPuProperty( persistenceUnit, USER ), - () -> extractPuProperty( persistenceUnit, JPA_JDBC_USER ) + () -> extractPuProperty( persistenceUnit, JPA_JDBC_USER ), + () -> extractPuProperty( persistenceUnit, JAKARTA_JPA_JDBC_USER ) ); //noinspection unchecked final Object effectivePass = NullnessHelper.coalesceSuppliedValues( () -> integrationSettingsCopy.remove( PASS ), () -> integrationSettingsCopy.remove( JPA_JDBC_PASSWORD ), + () -> integrationSettingsCopy.remove( JAKARTA_JPA_JDBC_PASSWORD ), () -> extractPuProperty( persistenceUnit, PASS ), - () -> extractPuProperty( persistenceUnit, JPA_JDBC_PASSWORD ) + () -> extractPuProperty( persistenceUnit, JPA_JDBC_PASSWORD ), + () -> extractPuProperty( persistenceUnit, JAKARTA_JPA_JDBC_PASSWORD ) ); if ( effectiveUser != null || effectivePass != null ) { @@ -645,11 +674,13 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil if ( effectiveUser != null ) { mergedSettings.configurationValues.put( USER, effectiveUser ); mergedSettings.configurationValues.put( JPA_JDBC_USER, effectiveUser ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_USER, effectiveUser ); } if ( effectivePass != null ) { mergedSettings.configurationValues.put( PASS, effectivePass ); mergedSettings.configurationValues.put( JPA_JDBC_PASSWORD, effectivePass ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_PASSWORD, effectivePass ); } } @@ -662,7 +693,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil MergedSettings mergedSettings) { PersistenceUnitTransactionType txnType = null; - final Object intgTxnType = integrationSettingsCopy.remove( JPA_TRANSACTION_TYPE ); + Object intgTxnType = integrationSettingsCopy.remove( JPA_TRANSACTION_TYPE ); + if ( intgTxnType == null ) { + intgTxnType = integrationSettingsCopy.remove( JAKARTA_JPA_TRANSACTION_TYPE ); + } if ( intgTxnType != null ) { txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( intgTxnType ); @@ -671,7 +705,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil txnType = persistenceUnit.getTransactionType(); } else { - final Object puPropTxnType = mergedSettings.configurationValues.get( JPA_TRANSACTION_TYPE ); + Object puPropTxnType = mergedSettings.configurationValues.get( JPA_TRANSACTION_TYPE ); + if ( puPropTxnType == null ) { + puPropTxnType = mergedSettings.configurationValues.get( JAKARTA_JPA_TRANSACTION_TYPE ); + } if ( puPropTxnType != null ) { txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( puPropTxnType ); } @@ -762,6 +799,21 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_JTA_DATASOURCE ) ) { + final Object dataSourceRef = integrationSettingsCopy.remove( JAKARTA_JPA_JTA_DATASOURCE ); + if ( dataSourceRef != null ) { + applyDataSource( + dataSourceRef, + true, + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + if ( integrationSettingsCopy.containsKey( JPA_NON_JTA_DATASOURCE ) ) { final Object dataSourceRef = integrationSettingsCopy.remove( JPA_NON_JTA_DATASOURCE ); @@ -776,6 +828,20 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil return; } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_NON_JTA_DATASOURCE ) ) { + final Object dataSourceRef = integrationSettingsCopy.remove( JAKARTA_JPA_NON_JTA_DATASOURCE ); + + applyDataSource( + dataSourceRef, + false, + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + if ( integrationSettingsCopy.containsKey( URL ) ) { // these have precedence over the JPA ones final Object integrationJdbcUrl = integrationSettingsCopy.get( URL ); @@ -786,8 +852,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil NullnessHelper.coalesceSuppliedValues( () -> ConfigurationHelper.getString( DRIVER, integrationSettingsCopy ), () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, integrationSettingsCopy ), () -> ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ), - () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ) + () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ) ), integrationSettingsCopy, mergedSettings @@ -818,6 +886,26 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_JDBC_URL ) ) { + final Object integrationJdbcUrl = integrationSettingsCopy.get( JAKARTA_JPA_JDBC_URL ); + + if ( integrationJdbcUrl != null ) { + //noinspection unchecked + applyJdbcSettings( + integrationJdbcUrl, + NullnessHelper.coalesceSuppliedValues( + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, integrationSettingsCopy ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ) + ), + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + if ( persistenceUnit.getJtaDataSource() != null ) { applyDataSource( persistenceUnit.getJtaDataSource(), @@ -874,6 +962,22 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( mergedSettings.configurationValues.containsKey( JAKARTA_JPA_JDBC_URL ) ) { + final Object url = mergedSettings.configurationValues.get( JAKARTA_JPA_JDBC_URL ); + + if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) { + applyJdbcSettings( + url, + ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ), + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + // any other conditions to account for? } @@ -894,31 +998,48 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // add to EMF properties (questionable - see HHH-13432) final String emfKey; final String inverseEmfKey; + final String jakartaEmfKey; + final String jakartaInverseEmfKey; if ( isJta ) { emfKey = JPA_JTA_DATASOURCE; + jakartaEmfKey = JAKARTA_JPA_JTA_DATASOURCE; inverseEmfKey = JPA_NON_JTA_DATASOURCE; + jakartaInverseEmfKey = JAKARTA_JPA_NON_JTA_DATASOURCE; } else { emfKey = JPA_NON_JTA_DATASOURCE; + jakartaEmfKey = JAKARTA_JPA_NON_JTA_DATASOURCE; inverseEmfKey = JPA_JTA_DATASOURCE; + jakartaInverseEmfKey = JAKARTA_JPA_JTA_DATASOURCE; } mergedSettings.configurationValues.put( emfKey, dataSourceRef ); + mergedSettings.configurationValues.put( jakartaEmfKey, dataSourceRef ); // clear any settings logically overridden by this datasource cleanUpConfigKeys( integrationSettingsCopy, mergedSettings, inverseEmfKey, + jakartaInverseEmfKey, JPA_JDBC_DRIVER, + JAKARTA_JPA_JDBC_DRIVER, DRIVER, JPA_JDBC_URL, + JAKARTA_JPA_JDBC_URL, URL ); // clean-up the entries in the "integration overrides" so they do not get get picked // up in the general "integration overrides" handling - cleanUpConfigKeys( integrationSettingsCopy, DATASOURCE, JPA_JTA_DATASOURCE, JPA_NON_JTA_DATASOURCE ); + cleanUpConfigKeys( + integrationSettingsCopy, + DATASOURCE, + JPA_JTA_DATASOURCE, + JAKARTA_JPA_JTA_DATASOURCE, + JPA_NON_JTA_DATASOURCE, + JAKARTA_JPA_NON_JTA_DATASOURCE + ); // add under Hibernate's DATASOURCE setting where the ConnectionProvider will find it mergedSettings.configurationValues.put( DATASOURCE, dataSourceRef ); @@ -952,14 +1073,17 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil MergedSettings mergedSettings) { mergedSettings.configurationValues.put( URL, url ); mergedSettings.configurationValues.put( JPA_JDBC_URL, url ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_URL, url ); if ( driver != null ) { mergedSettings.configurationValues.put( DRIVER, driver ); mergedSettings.configurationValues.put( JPA_JDBC_DRIVER, driver ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_DRIVER, driver ); } else { mergedSettings.configurationValues.remove( DRIVER ); mergedSettings.configurationValues.remove( JPA_JDBC_DRIVER ); + mergedSettings.configurationValues.remove( JAKARTA_JPA_JDBC_DRIVER ); } // clean up the integration-map values @@ -967,12 +1091,16 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil integrationSettingsCopy, DRIVER, JPA_JDBC_DRIVER, + JAKARTA_JPA_JDBC_DRIVER, URL, JPA_JDBC_URL, + JAKARTA_JPA_JDBC_URL, USER, JPA_JDBC_USER, + JAKARTA_JPA_JDBC_USER, PASS, - JPA_JDBC_PASSWORD + JPA_JDBC_PASSWORD, + JAKARTA_JPA_JDBC_PASSWORD ); cleanUpConfigKeys( @@ -980,7 +1108,9 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil mergedSettings, DATASOURCE, JPA_JTA_DATASOURCE, - JPA_NON_JTA_DATASOURCE + JAKARTA_JPA_JTA_DATASOURCE, + JPA_NON_JTA_DATASOURCE, + JAKARTA_JPA_NON_JTA_DATASOURCE ); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java index 2be47723e4..1565e5b68f 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java @@ -269,16 +269,29 @@ public class PersistenceXmlParser { if ( integration.containsKey( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ) { persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER ) ) { + persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER ) ); + } if ( integration.containsKey( AvailableSettings.JPA_TRANSACTION_TYPE ) ) { String transactionType = (String) integration.get( AvailableSettings.JPA_TRANSACTION_TYPE ); persistenceUnit.setTransactionType( parseTransactionType( transactionType ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE ) ) { + String transactionType = (String) integration.get( AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE ); + persistenceUnit.setTransactionType( parseTransactionType( transactionType ) ); + } if ( integration.containsKey( AvailableSettings.JPA_JTA_DATASOURCE ) ) { persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JPA_JTA_DATASOURCE ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE ) ) { + persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE ) ); + } if ( integration.containsKey( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ) { persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE ) ) { + persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE ) ); + } decodeTransactionType( persistenceUnit ); diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Bootstrap.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Bootstrap.java index 53677815e4..404ecfc60a 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Bootstrap.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Bootstrap.java @@ -62,7 +62,6 @@ public final class Bootstrap { String persistenceUnitName, PersistenceUnitTransactionType transactionType, Map integration) { - ; return new EntityManagerFactoryBuilderImpl( PersistenceXmlParser.parse( persistenceXmlUrl, transactionType, integration ).get( persistenceUnitName ), integration diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java index a88d09bc55..5e68309397 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java @@ -9,7 +9,6 @@ package org.hibernate.jpa.boot.spi; import java.util.Map; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; import org.hibernate.jpa.HibernatePersistenceProvider; @@ -100,7 +99,10 @@ public final class ProviderChecker { if ( integration == null ) { return null; } - final String setting = (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ); + String setting = (String) integration.get(AvailableSettings.JPA_PERSISTENCE_PROVIDER); + if ( setting == null ) { + setting = (String) integration.get(AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER); + } return setting == null ? null : setting.trim(); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java index 20e1ea641b..621258df6d 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java @@ -13,6 +13,8 @@ import javax.persistence.PessimisticLockScope; import org.hibernate.LockOptions; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; @@ -31,7 +33,12 @@ public final class LockOptionsHelper { * @param lockOptionsSupplier The reference to the lock to modify */ public static void applyPropertiesToLockOptions(final Map props, final Supplier lockOptionsSupplier) { - Object lockScope = props.get( JPA_LOCK_SCOPE ); + String lockScopeHint = JPA_LOCK_SCOPE; + Object lockScope = props.get( lockScopeHint ); + if ( lockScope == null ) { + lockScopeHint = JAKARTA_JPA_LOCK_SCOPE; + lockScope = props.get( lockScopeHint ); + } if ( lockScope instanceof String && PessimisticLockScope.valueOf( (String) lockScope ) == PessimisticLockScope.EXTENDED ) { lockOptionsSupplier.get().setScope( true ); } @@ -40,10 +47,15 @@ public final class LockOptionsHelper { lockOptionsSupplier.get().setScope( extended ); } else if ( lockScope != null ) { - throw new PersistenceException( "Unable to parse " + JPA_LOCK_SCOPE + ": " + lockScope ); + throw new PersistenceException( "Unable to parse " + lockScopeHint + ": " + lockScope ); } - Object lockTimeout = props.get( JPA_LOCK_TIMEOUT ); + String timeoutHint = JPA_LOCK_TIMEOUT; + Object lockTimeout = props.get( timeoutHint ); + if (lockTimeout == null) { + timeoutHint = JAKARTA_JPA_LOCK_TIMEOUT; + lockTimeout = props.get( timeoutHint ); + } int timeout = 0; boolean timeoutSet = false; if ( lockTimeout instanceof String ) { @@ -55,7 +67,7 @@ public final class LockOptionsHelper { timeoutSet = true; } else if ( lockTimeout != null ) { - throw new PersistenceException( "Unable to parse " + JPA_LOCK_TIMEOUT + ": " + lockTimeout ); + throw new PersistenceException( "Unable to parse " + timeoutHint + ": " + lockTimeout ); } if ( timeoutSet ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java index 170a7288a2..28cf0418c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java @@ -90,6 +90,10 @@ import org.hibernate.type.Type; import org.jboss.logging.Logger; import static org.hibernate.LockOptions.WAIT_FOREVER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -107,6 +111,9 @@ import static org.hibernate.jpa.QueryHints.HINT_LOADGRAPH; import static org.hibernate.jpa.QueryHints.HINT_NATIVE_SPACES; import static org.hibernate.jpa.QueryHints.HINT_READONLY; import static org.hibernate.jpa.QueryHints.HINT_TIMEOUT; +import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_FETCHGRAPH; +import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_LOADGRAPH; +import static org.hibernate.jpa.QueryHints.JAKARTA_SPEC_HINT_TIMEOUT; import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT; /** @@ -1003,16 +1010,19 @@ public abstract class AbstractProducedQuery implements QueryImplementor { if ( queryTimeout != null ) { hints.put( HINT_TIMEOUT, queryTimeout ); hints.put( SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); + hints.put( JAKARTA_SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); } final LockOptions lockOptions = getLockOptions(); final int lockOptionsTimeOut = lockOptions.getTimeOut(); if ( lockOptionsTimeOut != WAIT_FOREVER ) { hints.put( JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); + hints.put( JAKARTA_JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); } if ( lockOptions.getScope() ) { hints.put( JPA_LOCK_SCOPE, lockOptions.getScope() ); + hints.put( JAKARTA_JPA_LOCK_SCOPE, lockOptions.getScope() ); } if ( lockOptions.hasAliasSpecificLockModes() && canApplyAliasSpecificLockModeHints() ) { @@ -1031,7 +1041,9 @@ public abstract class AbstractProducedQuery implements QueryImplementor { if ( cacheStoreMode != null || cacheRetrieveMode != null ) { putIfNotNull( hints, HINT_CACHE_MODE, CacheModeHelper.interpretCacheMode( cacheStoreMode, cacheRetrieveMode ) ); putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, cacheRetrieveMode ); + putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, cacheRetrieveMode ); putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, cacheStoreMode ); + putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_STORE_MODE, cacheStoreMode ); } if ( isCacheable() ) { @@ -1072,12 +1084,12 @@ public abstract class AbstractProducedQuery implements QueryImplementor { if ( HINT_TIMEOUT.equals( hintName ) ) { applied = applyTimeoutHint( ConfigurationHelper.getInteger( value ) ); } - else if ( SPEC_HINT_TIMEOUT.equals( hintName ) ) { + else if ( SPEC_HINT_TIMEOUT.equals( hintName ) || JAKARTA_SPEC_HINT_TIMEOUT.equals( hintName ) ) { // convert milliseconds to seconds int timeout = (int)Math.round( ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 ); applied = applyTimeoutHint( timeout ); } - else if ( JPA_LOCK_TIMEOUT.equals( hintName ) ) { + else if ( JPA_LOCK_TIMEOUT.equals( hintName ) || JAKARTA_JPA_LOCK_TIMEOUT.equals( hintName ) ) { applied = applyLockTimeoutHint( ConfigurationHelper.getInteger( value ) ); } else if ( HINT_COMMENT.equals( hintName ) ) { @@ -1101,11 +1113,11 @@ public abstract class AbstractProducedQuery implements QueryImplementor { else if ( HINT_CACHE_MODE.equals( hintName ) ) { applied = applyCacheModeHint( ConfigurationHelper.getCacheMode( value ) ); } - else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) { + else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) { final CacheRetrieveMode retrieveMode = value != null ? CacheRetrieveMode.valueOf( value.toString() ) : null; applied = applyJpaCacheRetrieveMode( retrieveMode ); } - else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) { + else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) { final CacheStoreMode storeMode = value != null ? CacheStoreMode.valueOf( value.toString() ) : null; applied = applyJpaCacheStoreMode( storeMode ); } @@ -1133,7 +1145,10 @@ public abstract class AbstractProducedQuery implements QueryImplementor { applied = false; } } - else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) { + else if ( HINT_FETCHGRAPH.equals( hintName ) + || HINT_LOADGRAPH.equals( hintName ) + || JAKARTA_HINT_FETCHGRAPH.equals( hintName ) + || JAKARTA_HINT_LOADGRAPH.equals( hintName ) ) { if ( value instanceof RootGraph ) { applyGraph( (RootGraph) value, GraphSemantic.fromJpaHintName( hintName ) ); applyEntityGraphQueryHint( new EntityGraphQueryHint( hintName, (RootGraphImpl) value ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java index 61bf74b3f3..119ea6f9da 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java @@ -60,7 +60,10 @@ public class ManagedBeanRegistryInitiator implements StandardServiceInitiator Date: Tue, 20 Apr 2021 13:27:22 +0200 Subject: [PATCH 02/45] HHH-14274 Support for jakarta prefixed String properties for integrations --- .../BeanValidationIntegrator.java | 16 ++++++++-- .../beanvalidation/GroupsPerOperation.java | 22 +++++++++---- .../cfg/beanvalidation/TypeSafeActivator.java | 31 ++++++++++++++++--- .../spi/ManagedBeanRegistryInitiator.java | 7 ++++- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java index f2524f7144..7ef254e5f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java @@ -33,8 +33,10 @@ public class BeanValidationIntegrator implements Integrator { public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl"; public static final String BV_CHECK_CLASS = "javax.validation.ConstraintViolation"; + public static final String JAKARTA_BV_CHECK_CLASS = "jakarta.validation.ConstraintViolation"; public static final String MODE_PROPERTY = "javax.persistence.validation.mode"; + public static final String JAKARTA_MODE_PROPERTY = "jakarta.persistence.validation.mode"; private static final String ACTIVATOR_CLASS_NAME = "org.hibernate.cfg.beanvalidation.TypeSafeActivator"; private static final String VALIDATE_SUPPLIED_FACTORY_METHOD_NAME = "validateSuppliedFactory"; @@ -87,7 +89,11 @@ public class BeanValidationIntegrator implements Integrator { final SessionFactoryServiceRegistry serviceRegistry) { final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class ); // IMPL NOTE : see the comments on ActivationContext.getValidationModes() as to why this is multi-valued... - final Set modes = ValidationMode.getModes( cfgService.getSettings().get( MODE_PROPERTY ) ); + Object modeSetting = cfgService.getSettings().get( MODE_PROPERTY ); + if ( modeSetting == null ) { + modeSetting = cfgService.getSettings().get( JAKARTA_MODE_PROPERTY ); + } + final Set modes = ValidationMode.getModes( modeSetting ); if ( modes.size() > 1 ) { LOG.multipleValidationModes( ValidationMode.loggable( modes ) ); } @@ -157,7 +163,13 @@ public class BeanValidationIntegrator implements Integrator { return true; } catch (Exception e) { - return false; + try { + classLoaderService.classForName( JAKARTA_BV_CHECK_CLASS ); + return true; + } + catch (Exception e2) { + return false; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java index 525bc86b58..7776982c97 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java @@ -21,6 +21,7 @@ import org.hibernate.boot.spi.ClassLoaderAccess; */ public class GroupsPerOperation { private static final String JPA_GROUP_PREFIX = "javax.persistence.validation.group."; + private static final String JAKARTA_JPA_GROUP_PREFIX = "javax.persistence.validation.group."; private static final String HIBERNATE_GROUP_PREFIX = "org.hibernate.validator.group."; private static final Class[] DEFAULT_GROUPS = new Class[] { Default.class }; @@ -54,7 +55,10 @@ public class GroupsPerOperation { } public static Class[] buildGroupsForOperation(Operation operation, Map settings, ClassLoaderAccess classLoaderAccess) { - final Object property = settings.get( operation.getGroupPropertyName() ); + Object property = settings.get( operation.getGroupPropertyName() ); + if ( property == null ) { + property = settings.get( operation.getJakartaGroupPropertyName() ); + } if ( property == null ) { return operation == Operation.DELETE ? EMPTY_GROUPS : DEFAULT_GROUPS; @@ -95,18 +99,20 @@ public class GroupsPerOperation { } public static enum Operation { - INSERT("persist", JPA_GROUP_PREFIX + "pre-persist"), - UPDATE("update", JPA_GROUP_PREFIX + "pre-update"), - DELETE("remove", JPA_GROUP_PREFIX + "pre-remove"), - DDL("ddl", HIBERNATE_GROUP_PREFIX + "ddl"); + INSERT( "persist", JPA_GROUP_PREFIX + "pre-persist", JAKARTA_JPA_GROUP_PREFIX + "pre-persist" ), + UPDATE( "update", JPA_GROUP_PREFIX + "pre-update", JAKARTA_JPA_GROUP_PREFIX + "pre-update" ), + DELETE( "remove", JPA_GROUP_PREFIX + "pre-remove", JAKARTA_JPA_GROUP_PREFIX + "pre-remove" ), + DDL( "ddl", HIBERNATE_GROUP_PREFIX + "ddl", HIBERNATE_GROUP_PREFIX + "ddl" ); private final String exposedName; private final String groupPropertyName; + private final String jakartaGroupPropertyName; - Operation(String exposedName, String groupProperty) { + Operation(String exposedName, String groupProperty, String jakartaGroupPropertyName) { this.exposedName = exposedName; this.groupPropertyName = groupProperty; + this.jakartaGroupPropertyName = jakartaGroupPropertyName; } public String getName() { @@ -116,6 +122,10 @@ public class GroupsPerOperation { public String getGroupPropertyName() { return groupPropertyName; } + + public String getJakartaGroupPropertyName() { + return jakartaGroupPropertyName; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java index c75ea495cc..60c874da6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java @@ -33,6 +33,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.spi.ClassLoaderAccess; import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.config.spi.ConfigurationService; @@ -60,8 +61,6 @@ class TypeSafeActivator { private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TypeSafeActivator.class.getName()); - private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory"; - /** * Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory. * @@ -532,7 +531,7 @@ class TypeSafeActivator { @SuppressWarnings("unchecked") private static ValidatorFactory resolveProvidedFactory(ConfigurationService cfgService) { return cfgService.getSetting( - FACTORY_PROPERTY, + AvailableSettings.JPA_VALIDATION_FACTORY, new ConfigurationService.Converter() { @Override public ValidatorFactory convert(Object value) { @@ -544,7 +543,7 @@ class TypeSafeActivator { String.format( Locale.ENGLISH, "ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s", - FACTORY_PROPERTY, + AvailableSettings.JPA_VALIDATION_FACTORY, ValidatorFactory.class.getName(), value.getClass().getName() ) @@ -552,7 +551,29 @@ class TypeSafeActivator { } } }, - null + cfgService.getSetting( + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + new ConfigurationService.Converter() { + @Override + public ValidatorFactory convert(Object value) { + try { + return ValidatorFactory.class.cast( value ); + } + catch ( ClassCastException e ) { + throw new IntegrationException( + String.format( + Locale.ENGLISH, + "ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s", + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + ValidatorFactory.class.getName(), + value.getClass().getName() + ) + ); + } + } + }, + null + ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java index 119ea6f9da..105edf75ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java @@ -129,7 +129,12 @@ public class ManagedBeanRegistryInitiator implements StandardServiceInitiator Date: Thu, 22 Apr 2021 18:15:45 +0200 Subject: [PATCH 03/45] HHH-13946 Create Jakarta artifacts for hibernate-core, hibernate-envers, hibernate-jpamodelgen and hibernate-testing --- build.gradle | 1 + gradle/libraries.gradle | 28 +- .../hibernate-core-jakarta.gradle | 182 ++++++++++++ hibernate-core/hibernate-core.gradle | 6 +- .../cfgxmlpar/META-INF/persistence.xml | 0 .../jpa/test/pack/cfgxmlpar/hibernate.cfg.xml | 0 .../defaultpar/META-INF/orm.xml | 0 .../defaultpar/META-INF/persistence.xml | 0 .../jpa/test/pack/defaultpar/Mouse.hbm.xml | 0 .../defaultpar_1_0/META-INF/orm.xml | 0 .../defaultpar_1_0/META-INF/persistence.xml | 0 .../test/pack/defaultpar_1_0/Mouse1.hbm.xml | 0 .../excludehbmpar/META-INF/orm2.xml | 0 .../excludehbmpar/META-INF/persistence.xml | 0 .../jpa/test/pack/excludehbmpar/Mouse.hbm.xml | 0 .../explicitpar/META-INF/orm.xml | 0 .../explicitpar/META-INF/persistence.xml | 0 .../explicitpar2/META-INF/orm.xml | 0 .../explicitpar2/META-INF/persistence.xml | 0 .../explodedpar/META-INF/persistence.xml | 0 .../test/pack/explodedpar/Elephant.hbm.xml | 0 .../externaljar/META-INF/orm.xml | 0 .../overridenpar/META-INF/persistence.xml | 0 .../overridenpar/overridenpar.properties | 0 .../space par/META-INF/persistence.xml | 0 .../war/WEB-INF/classes/META-INF/orm.xml | 0 .../WEB-INF/classes/META-INF/persistence.xml | 0 .../hibernate/jpa/test/pack/war/Mouse.hbm.xml | 0 .../hibernate-envers-jakarta.gradle | 103 +++++++ hibernate-envers/hibernate-envers.gradle | 16 ++ .../hibernate-jboss-jta.gradle | 64 +++++ .../hibernate-testing-jakarta.gradle | 83 ++++++ hibernate-testing/hibernate-testing.gradle | 3 + .../hibernate-transaction-client.gradle | 62 +++++ .../hibernate-transaction-spi.gradle | 62 +++++ rules/jakarta-direct-modelgen.properties | 34 +++ rules/jakarta-direct.properties | 12 + rules/jakarta-renames.properties | 260 ++++++++++++++++++ rules/jakarta-versions.properties | 223 +++++++++++++++ settings.gradle | 12 + .../hibernate-jpamodelgen-jakarta.gradle | 68 +++++ .../hibernate/jpamodelgen/ClassWriter.java | 2 +- .../org/hibernate/jpamodelgen/Context.java | 12 +- 43 files changed, 1224 insertions(+), 9 deletions(-) create mode 100644 hibernate-core-jakarta/hibernate-core-jakarta.gradle rename hibernate-core/src/test/bundles/{ => templates}/cfgxmlpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar_1_0/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar_1_0/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/excludehbmpar/META-INF/orm2.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/excludehbmpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explicitpar/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explicitpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explicitpar2/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explicitpar2/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explodedpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/externaljar/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/overridenpar/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/overridenpar/overridenpar.properties (100%) rename hibernate-core/src/test/bundles/{ => templates}/space par/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/war/WEB-INF/classes/META-INF/orm.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/war/WEB-INF/classes/META-INF/persistence.xml (100%) rename hibernate-core/src/test/bundles/{ => templates}/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml (100%) create mode 100644 hibernate-envers-jakarta/hibernate-envers-jakarta.gradle create mode 100644 hibernate-jboss-jta/hibernate-jboss-jta.gradle create mode 100644 hibernate-testing-jakarta/hibernate-testing-jakarta.gradle create mode 100644 hibernate-transaction-client/hibernate-transaction-client.gradle create mode 100644 hibernate-transaction-spi/hibernate-transaction-spi.gradle create mode 100644 rules/jakarta-direct-modelgen.properties create mode 100644 rules/jakarta-direct.properties create mode 100644 rules/jakarta-renames.properties create mode 100644 rules/jakarta-versions.properties create mode 100644 tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle diff --git a/build.gradle b/build.gradle index 3690ac49ff..15ab92bf1c 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,7 @@ ext { ormVersion = new HibernateVersion( project.releaseVersion, project ) } jpaVersion = new JpaVersion('2.2') + jakartaJpaVersion = new JpaVersion('3.0.0') } // The Gradle Nexus Publish Plugin must be applied to the root project and requires group and version diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index c97a65f5b4..9b82ada14c 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -18,9 +18,11 @@ ext { hibernateValidatorVersion = '6.1.6.Final' validationApiVersion = '2.0.1.Final' elVersion = '3.0.1-b09' + hibernateValidatorJakartaVersion = '7.0.1.Final' cdiVersion = '2.0' weldVersion = '3.1.5.Final' + jakartaWeldVersion = '4.0.1.SP1' javassistVersion = '3.27.0-GA' byteBuddyVersion = '1.10.21' @@ -40,6 +42,7 @@ ext { // We can't upgrade JAXB in Karaf (yet), but fortunately everything works fine with the version built in Karaf jaxbApiVersionOsgiRange = "[2.2,3)" jaxbRuntimeVersion = '2.3.1' + jakartaJaxbRuntimeVersion = '3.0.0' //GraalVM graalvmVersion = '19.3.1' @@ -76,6 +79,18 @@ ext { // required by JAXB from JDK 9 as it is not available anymore in JDK 9 activation: 'javax.activation:javax.activation-api:1.2.0', + // jakarta + jakarta_jpa: "jakarta.persistence:jakarta.persistence-api:${project.jakartaJpaVersion}", + jakarta_jta: 'jakarta.transaction:jakarta.transaction-api:2.0.0', + jakarta_validation: 'jakarta.validation:jakarta.validation-api:3.0.0', + jakarta_jacc: 'jakarta.authorization:jakarta.authorization-api:2.0.0', + jakarta_interceptor: 'jakarta.interceptor:jakarta.interceptor-api:2.0.0', + jakarta_activation: 'jakarta.activation:jakarta.activation-api:2.0.1', + jakarta_resource: 'jakarta.resource:jakarta.resource-api:2.0.0', + jakarta_jaxb_api: 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.0', + jakarta_jaxb_runtime: "org.glassfish.jaxb:jaxb-runtime:${jakartaJaxbRuntimeVersion}", + jakarta_cdi: 'jakarta.enterprise:jakarta.enterprise.cdi-api:3.0.0', + // logging logging: 'org.jboss.logging:jboss-logging:3.4.1.Final', logging_annotations: 'org.jboss.logging:jboss-logging-annotations:2.1.0.Final', @@ -126,7 +141,11 @@ ext { jodaTime: "joda-time:joda-time:${jodaTimeVersion}", informix: 'com.ibm.informix:jdbc:4.10.12', - jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final", + jboss_jta: "org.jboss.narayana.jta:narayana-jta:5.11.1.Final", + jboss_tx_spi: "org.jboss:jboss-transaction-spi:7.6.0.Final", + // todo (jakarta): update the version when it is released + jboss_jta_jakarta: "org.jboss.narayana.jta:narayana-jta-jakarta:5.11.2.Final", + jboss_tx_spi_jakarta: "org.jboss:jboss-transaction-spi-jakarta:7.6.1.Final", xapool: "com.experlog:xapool:1.5.0", mockito: 'org.mockito:mockito-core:2.19.1', mockito_inline: 'org.mockito:mockito-inline:2.19.1', @@ -135,6 +154,10 @@ ext { // EL required by Hibernate Validator at test runtime expression_language: "org.glassfish:javax.el:${elVersion}", + jakarta_validator:"org.hibernate.validator:hibernate-validator:${hibernateValidatorJakartaVersion}", + // EL required by Hibernate Validator at test runtime + jakarta_el: 'org.glassfish:jakarta.el:4.0.1', + c3p0: "com.mchange:c3p0:0.9.5.5", ehcache: "net.sf.ehcache:ehcache:2.10.6", ehcache3: "org.ehcache:ehcache:3.6.1", @@ -151,6 +174,7 @@ ext { cdi: "javax.enterprise:cdi-api:${cdiVersion}", weld: "org.jboss.weld.se:weld-se-shaded:${weldVersion}", + jakarta_weld: "org.jboss.weld.se:weld-se-shaded:${jakartaWeldVersion}", assertj: "org.assertj:assertj-core:${assertjVersion}", @@ -163,6 +187,8 @@ ext { jboss_vfs: "org.jboss:jboss-vfs:3.2.11.Final", wildfly_transaction_client : 'org.wildfly.transaction:wildfly-transaction-client:1.1.7.Final', + // todo (jakarta): update the version when it is released + wildfly_transaction_client_jakarta : 'org.wildfly.transaction:wildfly-transaction-client-jakarta:1.2.0.Final-SNAPSHOT', jboss_ejb_spec_jar : 'org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final', jboss_annotation_spec_jar : 'org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:1.0.0.Final', diff --git a/hibernate-core-jakarta/hibernate-core-jakarta.gradle b/hibernate-core-jakarta/hibernate-core-jakarta.gradle new file mode 100644 index 0000000000..156d80a269 --- /dev/null +++ b/hibernate-core-jakarta/hibernate-core-jakarta.gradle @@ -0,0 +1,182 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +import org.apache.tools.ant.filters.ReplaceTokens + +description = 'Hibernate O/RM implementation of the Jakarta Persistence specification' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + tests { + description = 'Configuration for the produced test jar' + } + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jpa ) + // This can now be made provided + compile( libraries.javassist ) + // Could be made optional? + compile( libraries.byteBuddy ) + compile( libraries.antlr ) + compile( libraries.jakarta_jta ) + compile( libraries.jandex ) + compile( libraries.classmate ) + compile( libraries.jakarta_activation ) + + provided( libraries.jakarta_jacc ) + provided( libraries.jakarta_validation ) + provided( libraries.ant ) + provided( libraries.jakarta_cdi ) + + compile( libraries.dom4j ) + compile( libraries.commons_annotations ) + + compile( libraries.jakarta_jaxb_api ) + compile( libraries.jakarta_jaxb_runtime ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile( project(':hibernate-testing-jakarta') ) + testCompile fileTree(dir: 'libs', include: '*.jar') + + testCompile( libraries.shrinkwrap_api ) + testCompile( libraries.shrinkwrap ) + testCompile( libraries.jakarta_jacc ) + testCompile( libraries.jakarta_validation ) + testCompile( libraries.jandex ) + testCompile( libraries.classmate ) + testCompile( libraries.mockito ) + testCompile( libraries.mockito_inline ) + testCompile( libraries.jodaTime ) + testCompile( libraries.assertj ) + + testCompile( libraries.jakarta_cdi ) + + testCompile( libraries.jakarta_validator ) { + // for test runtime + transitive = true + } + + // for testing stored procedure support + testCompile( libraries.derby ) + + testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final" ) + testRuntime( libraries.jakarta_el ) + testRuntime( 'jaxen:jaxen:1.1' ) + testRuntime( libraries.javassist ) + testRuntime( libraries.byteBuddy ) + testRuntime( libraries.jakarta_weld ) + testRuntime( libraries.atomikos ) + testRuntime( libraries.atomikos_jta ) +// todo (jakarta): replace this when the jakarta artifact is released + testRuntime( project(':hibernate-transaction-client') ) +// testRuntime( libraries.wildfly_transaction_client_jakarta ) + + testCompile libraries.shrinkwrap_descriptors_api_javaee + testCompile libraries.shrinkwrap_descriptors_impl_javaee + + testCompile libraries.jboss_ejb_spec_jar + testCompile libraries.jboss_annotation_spec_jar +} + +jar { + mustRunAfter project(':hibernate-core').tasks.jar + mustRunAfter project(':hibernate-core').tasks.testJar + dependsOn project(':hibernate-core').tasks.jar + dependsOn project(':hibernate-core').tasks.testJar + def baseDir = project(':hibernate-core').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-core', 'hibernate-core-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} + +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +task copyBundleResources (type: Copy) { + dependsOn unpackTestJar + File unpackedDir = new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") + ext { + bundlesTargetDir = file( "${buildDir}/bundles" ) + bundleTokens = dbBundle[db] + ext.bundleTokens['buildDirName'] = buildDir.absolutePath + } + + from file("${buildDir}/unpacked/${unpackedDir.name}/templates") + into ext.bundlesTargetDir + filter( ReplaceTokens, tokens: ext.bundleTokens) + doFirst { + ext.bundlesTargetDir.mkdirs() + } +} + +processTestResources.dependsOn copyBundleResources + +artifacts { + tests new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") +} + +test { + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle index c47a0466ea..069335b2b7 100644 --- a/hibernate-core/hibernate-core.gradle +++ b/hibernate-core/hibernate-core.gradle @@ -25,7 +25,7 @@ sourceSets { // resources inherently exclude sources test { resources { - setSrcDirs( ['src/test/java','src/test/resources'] ) + setSrcDirs( ['src/test/java','src/test/resources','src/test/bundles'] ) } } @@ -145,6 +145,7 @@ jar { // For JPA, we don't want to target the automatically generated range, but a specific version "javax.persistence;version=\"${project.jpaVersion.osgiName}\"", // optionals + 'jakarta.persistence.spi;resolution:=optional', 'javax.management;resolution:=optional', 'javax.naming.event;resolution:=optional', 'javax.naming.spi;resolution:=optional', @@ -218,7 +219,7 @@ task copyBundleResources (type: Copy) { ext.bundleTokens['buildDirName'] = buildDir.absolutePath } - from file('src/test/bundles') + from file('src/test/bundles/templates') into ext.bundlesTargetDir filter( ReplaceTokens, tokens: ext.bundleTokens) @@ -229,6 +230,7 @@ task copyBundleResources (type: Copy) { processTestResources.dependsOn copyBundleResources task testJar(type: Jar, dependsOn: testClasses) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE archiveClassifier.set( 'test' ) from sourceSets.test.output } diff --git a/hibernate-core/src/test/bundles/cfgxmlpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/cfgxmlpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/cfgxmlpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/cfgxmlpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml b/hibernate-core/src/test/bundles/templates/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml similarity index 100% rename from hibernate-core/src/test/bundles/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml rename to hibernate-core/src/test/bundles/templates/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/defaultpar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/defaultpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/META-INF/orm2.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/orm2.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/META-INF/orm2.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/orm2.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/explicitpar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/explicitpar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explicitpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explicitpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explicitpar2/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar2/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar2/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar2/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explodedpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explodedpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explodedpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explodedpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml b/hibernate-core/src/test/bundles/templates/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml rename to hibernate-core/src/test/bundles/templates/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml diff --git a/hibernate-core/src/test/bundles/externaljar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/externaljar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/externaljar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/externaljar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/overridenpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/overridenpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/overridenpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/overridenpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/overridenpar/overridenpar.properties b/hibernate-core/src/test/bundles/templates/overridenpar/overridenpar.properties similarity index 100% rename from hibernate-core/src/test/bundles/overridenpar/overridenpar.properties rename to hibernate-core/src/test/bundles/templates/overridenpar/overridenpar.properties diff --git a/hibernate-core/src/test/bundles/space par/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/space par/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/space par/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/space par/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml diff --git a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle new file mode 100644 index 0000000000..66f4b74493 --- /dev/null +++ b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle @@ -0,0 +1,103 @@ +import org.apache.tools.ant.filters.ReplaceTokens + +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Hibernate\'s entity version (audit/history) support Jakarta edition' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( project( ':hibernate-core-jakarta' ) ) { + // Exclude access to this to avoid future use. + exclude group: "org.javassist", module: "javassist" + } + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + + testCompile( project( ':hibernate-testing-jakarta' ) ) + testCompile( project( ':hibernate-envers-jakarta' ) ) + testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) +} + +jar { + mustRunAfter project(':hibernate-envers').tasks.jar + mustRunAfter project(':hibernate-envers').tasks.testJar + dependsOn project(':hibernate-envers').tasks.jar + dependsOn project(':hibernate-envers').tasks.testJar + def baseDir = project(':hibernate-envers').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-envers', 'hibernate-envers-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} + +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +test { + dependsOn unpackTestJar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-envers/hibernate-envers.gradle b/hibernate-envers/hibernate-envers.gradle index a16dcbc335..5bcc7d4e9f 100644 --- a/hibernate-envers/hibernate-envers.gradle +++ b/hibernate-envers/hibernate-envers.gradle @@ -41,6 +41,12 @@ sourceSets { } } +configurations { + tests { + description = 'Configuration for the produced test jar' + } +} + jar { manifest { attributes( @@ -65,6 +71,16 @@ jar { } } +task testJar(type: Jar, dependsOn: testClasses) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + archiveClassifier.set( 'test' ) + from sourceSets.test.output +} + +artifacts { + tests testJar +} + tasks."matrix_mariadb" { beforeTest { descriptor -> println "Starting test: " + descriptor diff --git a/hibernate-jboss-jta/hibernate-jboss-jta.gradle b/hibernate-jboss-jta/hibernate-jboss-jta.gradle new file mode 100644 index 0000000000..e0331957af --- /dev/null +++ b/hibernate-jboss-jta/hibernate-jboss-jta.gradle @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'JBoss JTA transformed to be JTA 2.0 compatible' + +apply from: rootProject.file( 'gradle/java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jta ) + compile( libraries.jakarta_resource ) + compile( project(':hibernate-transaction-spi') ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile ( libraries.jboss_jta ) { + transitive=false; + } +} + +jar { + def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("narayana-jta-") } + inputs.files(sourceJarPath).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/hibernate-jboss-jta-' + project.version + ".jar" + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } +} \ No newline at end of file diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle new file mode 100644 index 0000000000..34aa2bed41 --- /dev/null +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -0,0 +1,83 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Support for testing Hibernate ORM Jakarta functionality' + +// todo (jakarta): replace this when the jakarta artifact is released +apply from: rootProject.file( 'gradle/java-module.gradle' ) +//apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile project( ':hibernate-core-jakarta' ) + compile( libraries.jakarta_jta ) + compile( libraries.junit ) + compile( libraries.byteman ) + compile( libraries.byteman_install ) + compile( libraries.byteman_bmunit ) + compile( libraries.xapool ) + compile( libraries.log4j ) +// todo (jakarta): replace this when the jakarta artifacts are released + compile project( ':hibernate-jboss-jta' ) +// compile( libraries.jboss_tx_spi_jakarta ) { +// transitive=false; +// } +// compile ( libraries.jboss_jta_jakarta ) { +// transitive=false; +// } + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile fileTree(dir: 'libs', include: '*.jar') +} + +jar { + mustRunAfter project(':hibernate-testing').tasks.jar + dependsOn project(':hibernate-testing').tasks.jar + def baseDir = project(':hibernate-testing').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-testing', 'hibernate-testing-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} \ No newline at end of file diff --git a/hibernate-testing/hibernate-testing.gradle b/hibernate-testing/hibernate-testing.gradle index c0f9fb4e30..abd8e3a5de 100644 --- a/hibernate-testing/hibernate-testing.gradle +++ b/hibernate-testing/hibernate-testing.gradle @@ -19,6 +19,9 @@ dependencies { compile( libraries.byteman_bmunit ) compile( libraries.xapool ) compile( libraries.log4j ) + compile( libraries.jboss_tx_spi ) { + transitive=false; + } compile ( libraries.jboss_jta ) { transitive=false; } diff --git a/hibernate-transaction-client/hibernate-transaction-client.gradle b/hibernate-transaction-client/hibernate-transaction-client.gradle new file mode 100644 index 0000000000..bd3cb0430b --- /dev/null +++ b/hibernate-transaction-client/hibernate-transaction-client.gradle @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Wildfly Transaction Client transformed to be JTA 2.0 compatible' + +apply from: rootProject.file( 'gradle/java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jta ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile ( libraries.wildfly_transaction_client ) { + transitive=false; + } +} + +jar { + def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("wildfly-transaction-client-") } + inputs.files(sourceJarPath).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/hibernate-transaction-client-' + project.version + ".jar" + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } +} \ No newline at end of file diff --git a/hibernate-transaction-spi/hibernate-transaction-spi.gradle b/hibernate-transaction-spi/hibernate-transaction-spi.gradle new file mode 100644 index 0000000000..57aced585f --- /dev/null +++ b/hibernate-transaction-spi/hibernate-transaction-spi.gradle @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Wildfly Transaction SPI transformed to be JTA 2.0 compatible' + +apply from: rootProject.file( 'gradle/java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jta ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile ( libraries.jboss_tx_spi ) { + transitive=false; + } +} + +jar { + def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("jboss-transaction-spi-") } + inputs.files(sourceJarPath).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/hibernate-transaction-spi-' + project.version + ".jar" + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } +} \ No newline at end of file diff --git a/rules/jakarta-direct-modelgen.properties b/rules/jakarta-direct-modelgen.properties new file mode 100644 index 0000000000..40142417e8 --- /dev/null +++ b/rules/jakarta-direct-modelgen.properties @@ -0,0 +1,34 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +# Direct String Replacement + +http\://java.sun.com/xml/ns/jaxb=https://jakarta.ee/xml/ns/jaxb + +# xmlBinding-3.0 properties +javax.xml.bind.JAXBElement=jakarta.xml.bind.JAXBElement + +com.sun.xml.bind.v2.ContextFactory=org.glassfish.jaxb.runtime.v2.JAXBContextFactory + +javax.annotation.security.RolesAllowed=jakarta.annotation.security.RolesAllowed + +javax.persistence.Entity=jakarta.persistence.Entity +javax.persistence.MappedSuperclass=jakarta.persistence.MappedSuperclass +javax.persistence.Embeddable=jakarta.persistence.Embeddable +javax.persistence.Id=jakarta.persistence.Id +javax.persistence.EmbeddedId=jakarta.persistence.EmbeddedId +javax.persistence.Transient=jakarta.persistence.Transient +javax.persistence.Basic=jakarta.persistence.Basic +javax.persistence.OneToOne=jakarta.persistence.OneToOne +javax.persistence.OneToMany=jakarta.persistence.OneToMany +javax.persistence.ManyToOne=jakarta.persistence.ManyToOne +javax.persistence.ManyToMany=jakarta.persistence.ManyToMany +javax.persistence.MapKeyClass=jakarta.persistence.MapKeyClass +javax.persistence.ElementCollection=jakarta.persistence.ElementCollection +javax.persistence.Access=jakarta.persistence.Access +javax.persistence.Convert=jakarta.persistence.Convert +javax.persistence.metamodel.StaticMetamodel=jakarta.persistence.metamodel.StaticMetamodel +javax.persistence.metamodel.SingularAttribute=jakarta.persistence.metamodel.SingularAttribute +javax.persistence.metamodel.CollectionAttribute=jakarta.persistence.metamodel.CollectionAttribute +javax.persistence.metamodel.SetAttribute=jakarta.persistence.metamodel.SetAttribute +javax.persistence.metamodel.ListAttribute=jakarta.persistence.metamodel.ListAttribute +javax.persistence.metamodel.MapAttribute=jakarta.persistence.metamodel.MapAttribute \ No newline at end of file diff --git a/rules/jakarta-direct.properties b/rules/jakarta-direct.properties new file mode 100644 index 0000000000..cd8e6b52ac --- /dev/null +++ b/rules/jakarta-direct.properties @@ -0,0 +1,12 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +# Direct String Replacement + +http\://java.sun.com/xml/ns/jaxb=https://jakarta.ee/xml/ns/jaxb + +# xmlBinding-3.0 properties +javax.xml.bind.JAXBElement=jakarta.xml.bind.JAXBElement + +com.sun.xml.bind.v2.ContextFactory=org.glassfish.jaxb.runtime.v2.JAXBContextFactory + +javax.annotation.security.RolesAllowed=jakarta.annotation.security.RolesAllowed diff --git a/rules/jakarta-renames.properties b/rules/jakarta-renames.properties new file mode 100644 index 0000000000..86e5ac487f --- /dev/null +++ b/rules/jakarta-renames.properties @@ -0,0 +1,260 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +com.sun.xml.bind=org.glassfish.jaxb.runtime +com.sun.xml.bind.api=org.glassfish.jaxb.runtime.api +com.sun.xml.bind.api.impl=org.glassfish.jaxb.core.api.impl +com.sun.xml.bind.marshaller=org.glassfish.jaxb.core.marshaller +com.sun.xml.bind.unmarshaller=org.glassfish.jaxb.core.unmarshaller +com.sun.xml.bind.util=org.glassfish.jaxb.runtime.util +com.sun.xml.bind.v2=org.glassfish.jaxb.runtime.v2 +com.sun.xml.bind.v2.model.annotation=org.glassfish.jaxb.runtime.v2.model.annotation +com.sun.xml.bind.v2.model.nav=org.glassfish.jaxb.core.v2.model.nav +com.sun.xml.bind.v2.model.runtime=org.glassfish.jaxb.runtime.v2.model.runtime +com.sun.xml.bind.v2.runtime=org.glassfish.jaxb.runtime.v2.runtime +com.sun.xml.bind.v2.runtime.unmarshaller=org.glassfish.jaxb.runtime.v2.runtime.unmarshaller +com.sun.xml.bind.v2.schemagen=org.glassfish.jaxb.runtime.v2.schemagen +com.sun.xml.bind.v2.schemagen.xmlschema=org.glassfish.jaxb.runtime.v2.schemagen.xmlschema +com.sun.xml.bind.v2.util=org.glassfish.jaxb.runtime.v2.util +com.sun.xml.internal.bind=org.glassfish.jaxb + +javax.activation=jakarta.activation +javax.annotation.security=jakarta.annotation.security +javax.annotation.sql=jakarta.annotation.sql +javax.annotation=jakarta.annotation +javax.batch.api=jakarta.batch.api +javax.batch.api.chunk=jakarta.batch.api.chunk +javax.batch.api.chunk.listener=jakarta.batch.api.chunk.listener +javax.batch.api.listener=jakarta.batch.api.listener +javax.batch.api.partition=jakarta.batch.api.partition +javax.batch.operations=jakarta.batch.operations +javax.batch.runtime=jakarta.batch.runtime +javax.batch.runtime.context=jakarta.batch.runtime.context +javax.decorator=jakarta.decorator +javax.ejb=jakarta.ejb +javax.ejb.embeddable=jakarta.ejb.embeddable +javax.ejb.spi=jakarta.ejb.spi +javax.el=jakarta.el +javax.enterprise.concurrent=jakarta.enterprise.concurrent +javax.enterprise.context.control=jakarta.enterprise.context.control +javax.enterprise.context.spi=jakarta.enterprise.context.spi +javax.enterprise.context=jakarta.enterprise.context +javax.enterprise.event=jakarta.enterprise.event +javax.enterprise.inject.literal=jakarta.enterprise.inject.literal +javax.enterprise.inject.se=jakarta.enterprise.inject.se +javax.enterprise.inject.spi.configurator=jakarta.enterprise.inject.spi.configurator +javax.enterprise.inject.spi=jakarta.enterprise.inject.spi +javax.enterprise.inject=jakarta.enterprise.inject +javax.enterprise.util=jakarta.enterprise.util +javax.faces=jakarta.faces +javax.faces.annotation=jakarta.faces.annotation +javax.faces.application=jakarta.faces.application +javax.faces.bean=jakarta.faces.bean +javax.faces.component=jakarta.faces.component +javax.faces.component.behavior=jakarta.faces.component.behavior +javax.faces.component.html=jakarta.faces.component.html +javax.faces.component.search=jakarta.faces.component.search +javax.faces.component.visit=jakarta.faces.component.visit +javax.faces.context=jakarta.faces.context +javax.faces.convert=jakarta.faces.convert +javax.faces.el=jakarta.faces.el +javax.faces.event=jakarta.faces.event +javax.faces.flow=jakarta.faces.flow +javax.faces.flow.builder=jakarta.faces.flow.builder +javax.faces.lifecycle=jakarta.faces.lifecycle +javax.faces.model=jakarta.faces.model +javax.faces.push=jakarta.faces.push +javax.faces.render=jakarta.faces.render +javax.faces.validator=jakarta.faces.validator +javax.faces.view=jakarta.faces.view +javax.faces.view.facelets=jakarta.faces.view.facelets +javax.faces.webapp=jakarta.faces.webapp +javax.inject=jakarta.inject +javax.interceptor=jakarta.interceptor +javax.jms=jakarta.jms +javax.json.bind.adapter=jakarta.json.bind.adapter +javax.json.bind.annotation=jakarta.json.bind.annotation +javax.json.bind.config=jakarta.json.bind.config +javax.json.bind.serializer=jakarta.json.bind.serializer +javax.json.bind.spi=jakarta.json.bind.spi +javax.json.bind=jakarta.json.bind +javax.json.spi=jakarta.json.spi +javax.json.stream=jakarta.json.stream +javax.json=jakarta.json +javax.jws=jakarta.jws +javax.jws.soap=jakarta.jws.soap +javax.mail=jakarta.mail +javax.persistence.criteria=jakarta.persistence.criteria +javax.persistence.metamodel=jakarta.persistence.metamodel +javax.persistence.spi=jakarta.persistence.spi +javax.persistence=jakarta.persistence +javax.persistence.cache.storeMode=jakarta.persistence.cache.storeMode +javax.persistence.cache.retrieveMode=jakarta.persistence.cache.retrieveMode +javax.persistence.bean.manager=jakarta.persistence.bean.manager +javax.persistence.validation.factory=jakarta.persistence.validation.factory +javax.resource.cci=jakarta.resource.cci +javax.resource.spi.endpoint=jakarta.resource.spi.endpoint +javax.resource.spi.security=jakarta.resource.spi.security +javax.resource.spi.work=jakarta.resource.spi.work +javax.resource.spi=jakarta.resource.spi +javax.resource=jakarta.resource +javax.security.auth.message=jakarta.security.auth.message +javax.security.auth.message.callback=jakarta.security.auth.message.callback +javax.security.auth.message.config=jakarta.security.auth.message.config +javax.security.auth.message.module=jakarta.security.auth.message.module +javax.security.enterprise=jakarta.security.enterprise +javax.security.enterprise.authentication.mechanism.http=jakarta.security.enterprise.authentication.mechanism.http +javax.security.enterprise.credential=jakarta.security.enterprise.credential +javax.security.enterprise.identitystore=jakarta.security.enterprise.identitystore +javax.security.jacc=jakarta.security.jacc +javax.servlet.annotation=jakarta.servlet.annotation +javax.servlet.descriptor=jakarta.servlet.descriptor +javax.servlet.http=jakarta.servlet.http +javax.servlet.jsp.el=jakarta.servlet.jsp.el +javax.servlet.jsp.jstl.core=jakarta.servlet.jsp.jstl.core +javax.servlet.jsp.jstl.fmt=jakarta.servlet.jsp.jstl.fmt +javax.servlet.jsp.jstl.sql=jakarta.servlet.jsp.jstl.sql +javax.servlet.jsp.jstl.tlv=jakarta.servlet.jsp.jstl.tlv +javax.servlet.jsp.jstl=jakarta.servlet.jsp.jstl +javax.servlet.jsp.resources=jakarta.servlet.jsp.resources +javax.servlet.jsp.tagext=jakarta.servlet.jsp.tagext +javax.servlet.jsp=jakarta.servlet.jsp +javax.servlet.resources=jakarta.servlet.resources +javax.servlet=jakarta.servlet +javax.transaction=jakarta.transaction +javax.validation=jakarta.validation +javax.validation.bootstrap=jakarta.validation.bootstrap +javax.validation.constraints=jakarta.validation.constraints +javax.validation.constraintvalidation=jakarta.validation.constraintvalidation +javax.validation.executable=jakarta.validation.executable +javax.validation.groups=jakarta.validation.groups +javax.validation.metadata=jakarta.validation.metadata +javax.validation.spi=jakarta.validation.spi +javax.validation.valueextraction=jakarta.validation.valueextraction +javax.websocket=jakarta.websocket +javax.websocket.server=jakarta.websocket.server +javax.ws.rs=jakarta.ws.rs +javax.ws.rs.client=jakarta.ws.rs.client +javax.ws.rs.container=jakarta.ws.rs.container +javax.ws.rs.core=jakarta.ws.rs.core +javax.ws.rs.ext=jakarta.ws.rs.ext +javax.ws.rs.sse=jakarta.ws.rs.sse +javax.xml.bind.annotation.adapters=jakarta.xml.bind.annotation.adapters +javax.xml.bind.annotation=jakarta.xml.bind.annotation +javax.xml.bind.attachment=jakarta.xml.bind.attachment +javax.xml.bind.helpers=jakarta.xml.bind.helpers +javax.xml.bind.util=jakarta.xml.bind.util +javax.xml.bind=jakarta.xml.bind +javax.xml.soap=jakarta.xml.soap +javax.xml.ws=jakarta.xml.ws +javax.xml.ws.handler=jakarta.xml.ws.handler +javax.xml.ws.handler.soap=jakarta.xml.ws.handler.soap +javax.xml.ws.http=jakarta.xml.ws.http +javax.xml.ws.soap=jakarta.xml.ws.soap +javax.xml.ws.spi=jakarta.xml.ws.spi +javax.xml.ws.spi.http=jakarta.xml.ws.spi.http +javax.xml.ws.wsaddressing=jakarta.xml.ws.wsaddressing + + +#Required for common enterprise beans test tools +com.ibm.websphere.ejbcontainer.test.mdb=io.openliberty.ejbcontainer.jakarta.test.mdb +com.ibm.websphere.ejbcontainer.test.mdb.interceptors=io.openliberty.ejbcontainer.jakarta.test.mdb.interceptors +com.ibm.websphere.ejbcontainer.test.osgi.pmi=io.openliberty.ejbcontainer.jakarta.test.osgi.pmi +com.ibm.websphere.ejbcontainer.test.osgi.pmi.internal=io.openliberty.ejbcontainer.jakarta.test.osgi.pmi.internal +com.ibm.websphere.ejbcontainer.test.tools=io.openliberty.ejbcontainer.jakarta.test.tools + +#Required to transform the package versions only +com.ibm.wsspi.el=com.ibm.wsspi.el +org.apache.myfaces.cdi.util=org.apache.myfaces.cdi.util +org.apache.myfaces.config.annotation=org.apache.myfaces.config.annotation +org.apache.myfaces.ee=org.apache.myfaces.ee +org.apache.myfaces.shared.util=org.apache.myfaces.shared.util +org.apache.myfaces.spi=org.apache.myfaces.spi +org.apache.myfaces.util=org.apache.myfaces.util +org.apache.myfaces.webapp=org.apache.myfaces.webapp +org.hibernate.validator=org.hibernate.validator +org.hibernate.validator.cdi.internal=org.hibernate.validator.cdi.internal +org.hibernate.validator.cdi=org.hibernate.validator.cdi +org.hibernate.validator.internal.engine.valueextraction=org.hibernate.validator.internal.engine.valueextraction +org.hibernate.validator.internal.properties=org.hibernate.validator.internal.properties +org.hibernate.validator.internal.util.classhierarchy=org.hibernate.validator.internal.util.classhierarchy +org.hibernate.validator.internal.util.logging=org.hibernate.validator.internal.util.logging +org.hibernate.validator.internal.util.privilegedactions=org.hibernate.validator.internal.util.privilegedactions +org.hibernate.validator.internal.util=org.hibernate.validator.internal.util +org.hibernate.validator.internal=org.hibernate.validator.internal +org.hibernate.validator.spi.properties=org.hibernate.validator.spi.properties +org.jboss.weld.annotated.enhanced=org.jboss.weld.annotated.enhanced +org.jboss.weld.bean.builtin=org.jboss.weld.bean.builtin +org.jboss.weld.bean.proxy=org.jboss.weld.bean.proxy +org.jboss.weld.bean.proxy.util=org.jboss.weld.bean.proxy.util +org.jboss.weld.bean=org.jboss.weld.bean +org.jboss.weld.bootstrap.api.helpers=org.jboss.weld.bootstrap.api.helpers +org.jboss.weld.bootstrap.api=org.jboss.weld.bootstrap.api +org.jboss.weld.bootstrap.spi.helpers=org.jboss.weld.bootstrap.spi.helpers +org.jboss.weld.bootstrap.spi=org.jboss.weld.bootstrap.spi +org.jboss.weld.bootstrap=org.jboss.weld.bootstrap +org.jboss.weld.config=org.jboss.weld.config +org.jboss.weld.construction.api=org.jboss.weld.construction.api +org.jboss.weld.context=org.jboss.weld.context +org.jboss.weld.context.api=org.jboss.weld.context.api +org.jboss.weld.context.bound=org.jboss.weld.context.bound +org.jboss.weld.context.http=org.jboss.weld.context.http +org.jboss.weld.contexts=org.jboss.weld.contexts +org.jboss.weld.ejb.api=org.jboss.weld.ejb.api +org.jboss.weld.ejb.spi=org.jboss.weld.ejb.spi +org.jboss.weld.exceptions=org.jboss.weld.exceptions +org.jboss.weld.executor=org.jboss.weld.executor +org.jboss.weld.injection.spi=org.jboss.weld.injection.spi +org.jboss.weld.injection=org.jboss.weld.injection +org.jboss.weld.interceptor.spi.model=org.jboss.weld.interceptor.spi.model +org.jboss.weld.manager.api=org.jboss.weld.manager.api +org.jboss.weld.manager=org.jboss.weld.manager +org.jboss.weld.metadata=org.jboss.weld.metadata +org.jboss.weld.module.ejb=org.jboss.weld.module.ejb +org.jboss.weld.module.jsf=org.jboss.weld.module.jsf +org.jboss.weld.module.web.el=org.jboss.weld.module.web.el +org.jboss.weld.module.web.servlet=org.jboss.weld.module.web.servlet +org.jboss.weld.probe=org.jboss.weld.probe +org.jboss.weld.resolution=org.jboss.weld.resolution +org.jboss.weld.resources.spi=org.jboss.weld.resources.spi +org.jboss.weld.resources=org.jboss.weld.resources +org.jboss.weld.security.spi=org.jboss.weld.security.spi +org.jboss.weld.serialization.spi=org.jboss.weld.serialization.spi +org.jboss.weld.transaction.spi=org.jboss.weld.transaction.spi +org.jboss.weld.util.collections=org.jboss.weld.util.collections +org.jboss.weld=org.jboss.weld + +org.eclipse.persistence.exceptions=org.eclipse.persistence.exceptions +org.eclipse.persistence.logging=org.eclipse.persistence.logging +org.eclipse.persistence.platform.server=org.eclipse.persistence.platform.server +org.eclipse.persistence.internal.databaseaccess=org.eclipse.persistence.internal.databaseaccess +org.eclipse.persistence.internal.helper=org.eclipse.persistence.internal.helper +org.eclipse.persistence.internal.security=org.eclipse.persistence.internal.security +org.eclipse.persistence.internal.sessions=org.eclipse.persistence.internal.sessions + +org.eclipse.persistence.annotations=org.eclipse.persistence.annotations +org.eclipse.persistence.descriptors=org.eclipse.persistence.descriptors +org.eclipse.persistence.descriptors.changetracking=org.eclipse.persistence.descriptors.changetracking +org.eclipse.persistence.queries=org.eclipse.persistence.queries +org.eclipse.persistence.indirection=org.eclipse.persistence.indirection +org.eclipse.persistence.internal.descriptors=org.eclipse.persistence.internal.descriptors +org.eclipse.persistence.internal.identitymaps=org.eclipse.persistence.internal.identitymaps +org.eclipse.persistence.internal.jpa=org.eclipse.persistence.internal.jpa +org.eclipse.persistence.internal.jpa.rs.metadata.model=org.eclipse.persistence.internal.jpa.rs.metadata.model +org.eclipse.persistence.internal.weaving=org.eclipse.persistence.internal.weaving +org.eclipse.persistence.jpa=org.eclipse.persistence.jpa +org.eclipse.persistence.platform.server.was=org.eclipse.persistence.platform.server.was +org.eclipse.persistence.internal.sessions.cdi=org.eclipse.persistence.internal.sessions.cdi +org.eclipse.persistence.platform.database=org.eclipse.persistence.platform.database +org.eclipse.persistence.sessions=org.eclipse.persistence.sessions +org.eclipse.persistence.tools.schemaframework=org.eclipse.persistence.tools.schemaframework +org.eclipse.persistence.transaction=org.eclipse.persistence.transaction + +com.sun.xml.internal.messaging.saaj.packaging.mime=com.sun.xml.messaging.saaj.packaging.mime +com.sun.xml.internal.messaging.saaj.packaging.mime.internet=com.sun.xml.messaging.saaj.packaging.mime.internet +com.sun.xml.internal.messaging.saaj.packaging.mime.util=com.sun.xml.messaging.saaj.packaging.mime.util +com.sun.xml.internal.messaging.saaj.soap=com.sun.xml.messaging.saaj.soap +com.sun.xml.internal.messaging.saaj.soap.dynamic=com.sun.xml.messaging.saaj.soap.dynamic +com.sun.xml.internal.messaging.saaj.soap.name=com.sun.xml.messaging.saaj.soap.name +com.sun.xml.internal.messaging.saaj.util=com.sun.xml.messaging.saaj.util +com.sun.xml.internal.messaging.saaj.util.stax=com.sun.xml.messaging.saaj.util.stax +com.sun.xml.internal.messaging.saaj.util.transform=com.sun.xml.messaging.saaj.util.transform diff --git a/rules/jakarta-versions.properties b/rules/jakarta-versions.properties new file mode 100644 index 0000000000..e43ebefeb4 --- /dev/null +++ b/rules/jakarta-versions.properties @@ -0,0 +1,223 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +com.ibm.wsspi.el=[4.0,5) +jakarta.activation=[2.0,3) +jakarta.annotation.security=[2.0,3) +jakarta.annotation.sql=[2.0,3) +jakarta.annotation=[2.0,3) +jakarta.batch.api=[2.0,3) +jakarta.batch.api.chunk=[2.0,3) +jakarta.batch.api.chunk.listener=[2.0,3) +jakarta.batch.api.listener=[2.0,3) +jakarta.batch.api.partition=[2.0,3) +jakarta.batch.operations=[2.0,3) +jakarta.batch.runtime=[2.0,3) +jakarta.batch.runtime.context=[2.0,3) +jakarta.decorator=[3.0,4.0) +jakarta.ejb=[4.0,5) +jakarta.ejb.embeddable=[4.0,5) +jakarta.ejb.spi=[4.0,5) +jakarta.el=[4.0,5) +jakarta.enterprise.concurrent=[2.0,3) +jakarta.enterprise.context.control=[3.0,4.0) +jakarta.enterprise.context.spi=[3.0,4.0) +jakarta.enterprise.context=[3.0,4.0) +jakarta.enterprise.event=[3.0,4.0) +jakarta.enterprise.inject.literal=[3.0,4.0) +jakarta.enterprise.inject.spi.configurator=[3.0,4.0) +jakarta.enterprise.inject.spi=[3.0,4.0) +jakarta.enterprise.inject=[3.0,4.0) +jakarta.enterprise.util=[3.0,4.0) +jakarta.faces=[3.0,4.0) +jakarta.faces.application=[3.0,4.0) +jakarta.faces.bean=[3.0,4.0) +jakarta.faces.component=[3.0,4.0) +jakarta.faces.component.behavior=[3.0,4.0) +jakarta.faces.context=[3.0,4.0) +jakarta.faces.convert=[3.0,4.0) +jakarta.faces.event=[3.0,4.0) +jakarta.faces.model=[3.0,4.0) +jakarta.faces.render=[3.0,4.0) +jakarta.faces.validator=[3.0,4.0) +jakarta.faces.view.facelets=[3.0,4.0) +jakarta.faces.webapp=[3.0,4.0) +jakarta.inject=[2.0,3.0) +jakarta.interceptor=[2.0,3.0) +jakarta.json.bind.adapter=[2.0,3.0) +jakarta.json.bind.annotation=[2.0,3.0) +jakarta.json.bind.config=[2.0,3.0) +jakarta.json.bind.serializer=[2.0,3.0) +jakarta.json.bind.spi=[2.0,3.0) +jakarta.json.bind=[2.0,3.0) +jakarta.json.spi=[2.0,3.0) +jakarta.json.stream=[2.0,3.0) +jakarta.json=[2.0,3.0) +jakarta.jms=[3.0,4) +jakarta.jws=[3.0,4) +jakarta.jws.soap=[3.0,4) +jakarta.persistence.criteria=[3.0,4) +jakarta.persistence.metamodel=[3.0,4) +jakarta.persistence.spi=[3.0,4) +jakarta.persistence=[3.0,4) +jakarta.resource.cci=[2.0,3) +jakarta.resource.spi.endpoint=[2.0,3) +jakarta.resource.spi.security=[2.0,3) +jakarta.resource.spi.work=[2.0,3) +jakarta.resource.spi=[2.0,3) +jakarta.resource=[2.0,3) +jakarta.security.auth.message=[2.0,3) +jakarta.security.auth.message.callback=[2.0,3) +jakarta.security.auth.message.config=[2.0,3) +jakarta.security.auth.message.module=[2.0,3) +jakarta.security.enterprise=[2.0,3) +jakarta.security.enterprise.authentication.mechanism.http=[2.0,3) +jakarta.security.enterprise.credential=[2.0,3) +jakarta.security.enterprise.identitystore=[2.0,3) +jakarta.security.jacc=[2.0,3) +jakarta.servlet.annotation=[5.0,6) +jakarta.servlet.descriptor=[5.0,6) +jakarta.servlet.http=[5.0,6) +jakarta.servlet.jsp.el=[3.0,4) +jakarta.servlet.jsp.jstl.core=[2.0,3) +jakarta.servlet.jsp.jstl.fmt=[2.0,3) +jakarta.servlet.jsp.jstl.sql=[2.0,3) +jakarta.servlet.jsp.jstl.tlv=[2.0,3) +jakarta.servlet.jsp.jstl=[2.0,3) +jakarta.servlet.jsp.resources=[3.0,4) +jakarta.servlet.jsp.tagext=[3.0,4) +jakarta.servlet.jsp=[3.0,4) +jakarta.servlet.resources=[5.0,6) +jakarta.servlet=[5.0,6) +jakarta.transaction=[2.0,3) +jakarta.validation=[3.0,4) +jakarta.validation.bootstrap=[3.0,4) +jakarta.validation.constraints=[3.0,4) +jakarta.validation.constraintvalidation=[3.0,4) +jakarta.validation.executable=[3.0,4) +jakarta.validation.groups=[3.0,4) +jakarta.validation.metadata=[3.0,4) +jakarta.validation.spi=[3.0,4) +jakarta.validation.valueextraction=[3.0,4) +jakarta.ws.rs=[3.0,4.0) +jakarta.ws.rs.client=[3.0,4.0) +jakarta.ws.rs.container=[3.0,4.0) +jakarta.ws.rs.core=[3.0,4.0) +jakarta.ws.rs.ext=[3.0,4.0) +jakarta.ws.rs.sse=[3.0,4.0) +jakarta.xml.bind.annotation.adapters=[3.0,4) +jakarta.xml.bind.annotation=[3.0,4) +jakarta.xml.bind.attachment=[3.0,4) +jakarta.xml.bind.helpers=[3.0,4) +jakarta.xml.bind.util=[3.0,4) +jakarta.xml.bind=[3.0,4) +jakarta.xml.soap=[3.0,4) +jakarta.xml.ws=[3.0,4) +jakarta.xml.ws.handler=[3.0,4) +jakarta.xml.ws.handler.soap=[3.0,4) +jakarta.xml.ws.http=[3.0,4) +jakarta.xml.ws.soap=[3.0,4) +jakarta.xml.ws.spi=[3.0,4) +jakarta.xml.ws.spi.http=[3.0,4) +jakarta.xml.ws.wsaddressing=[3.0,4) +jakarta.websocket=[2.0,3) +jakarta.websocket.server=[2.0,3) +org.apache.myfaces.cdi.util=[3.0,4) +org.apache.myfaces.config.annotation=[3.0,4) +org.apache.myfaces.ee=[3.0,4) +org.apache.myfaces.shared.util=[3.0,4) +org.apache.myfaces.spi=[3.0,4) +org.apache.myfaces.util=[3.0,4) +org.apache.myfaces.webapp=[3.0,4) +org.glassfish.jaxb.runtime=[3.0,4) +org.glassfish.jaxb.runtime.api=[3.0,4) +org.glassfish.jaxb.core.api.impl=[3.0,4) +org.glassfish.jaxb.core.marshaller=[3.0,4) +org.glassfish.jaxb.core.unmarshaller=[3.0,4) +org.glassfish.jaxb.runtime.util=[3.0,4) +org.glassfish.jaxb.core.v2.model.nav=[3.0,4) +org.glassfish.jaxb.runtime.v2=[3.0,4) +org.glassfish.jaxb.runtime.v2.model.annotation=[3.0,4) +org.glassfish.jaxb.runtime.v2.model.runtime=[3.0,4) +org.glassfish.jaxb.runtime.v2.runtime=[3.0,4) +org.glassfish.jaxb.runtime.v2.runtime.unmarshaller=[3.0,4) +org.glassfish.jaxb.runtime.v2.schemagen=[3.0,4) +org.glassfish.jaxb.runtime.v2.schemagen.xmlschema=[3.0,4) +org.glassfish.jaxb.runtime.v2.util=[3.0,4) +org.glassfish.jaxb=[3.0,4) +org.hibernate.validator=[7.0,8) +org.hibernate.validator.cdi.internal=[7.0,8) +org.hibernate.validator.cdi=[7.0,8) +org.hibernate.validator.internal.engine.valueextraction=[7.0,8) +org.hibernate.validator.internal.properties=[7.0,8) +org.hibernate.validator.internal.util.classhierarchy=[7.0,8) +org.hibernate.validator.internal.util.logging=[7.0,8) +org.hibernate.validator.internal.util.privilegedactions=[7.0,8) +org.hibernate.validator.internal.util=[7.0,8) +org.hibernate.validator.internal=[7.0,8) +org.hibernate.validator.spi.properties=[7.0,8) +org.jboss.weld.annotated.enhanced=[4.0,5) +org.jboss.weld.bean.builtin=[4.0,5) +org.jboss.weld.bean.proxy=[4.0,5) +org.jboss.weld.bean.proxy.util=[4.0,5) +org.jboss.weld.bean=[4.0,5) +org.jboss.weld.bootstrap.api.helpers=[4.0,5) +org.jboss.weld.bootstrap.api=[4.0,5) +org.jboss.weld.bootstrap.spi.helpers=[4.0,5) +org.jboss.weld.bootstrap.spi=[4.0,5) +org.jboss.weld.bootstrap=[4.0,5) +org.jboss.weld.config=[4.0,5) +org.jboss.weld.construction.api=[4.0,5) +org.jboss.weld.context=[4.0,5) +org.jboss.weld.context.api=[4.0,5) +org.jboss.weld.context.bound=[4.0,5) +org.jboss.weld.context.http=[4.0,5) +org.jboss.weld.contexts=[4.0,5) +org.jboss.weld.ejb.api=[4.0,5) +org.jboss.weld.ejb.spi=[4.0,5) +org.jboss.weld.exceptions=[4.0,5) +org.jboss.weld.executor=[4.0,5) +org.jboss.weld.injection.spi=[4.0,5) +org.jboss.weld.injection=[4.0,5) +org.jboss.weld.interceptor.spi.model=[4.0,5) +org.jboss.weld.manager.api=[4.0,5) +org.jboss.weld.manager=[4.0,5) +org.jboss.weld.metadata=[4.0,5) +org.jboss.weld.module.ejb=[4.0,5) +org.jboss.weld.module.jsf=[4.0,5) +org.jboss.weld.module.web.el=[4.0,5) +org.jboss.weld.module.web.servlet=[4.0,5) +org.jboss.weld.probe=[4.0,5) +org.jboss.weld.resolution=[4.0,5) +org.jboss.weld.resources.spi=[4.0,5) +org.jboss.weld.resources=[4.0,5) +org.jboss.weld.security.spi=[4.0,5) +org.jboss.weld.serialization.spi=[4.0,5) +org.jboss.weld.transaction.spi=[4.0,5) +org.jboss.weld.util.collections=[4.0,5) +org.jboss.weld=[4.0,5) + +org.eclipse.persistence.exceptions=[3.0,4) +org.eclipse.persistence.logging=[3.0,4) +org.eclipse.persistence.platform.server=[3.0,4) +org.eclipse.persistence.internal.databaseaccess=[3.0,4) +org.eclipse.persistence.internal.helper=[3.0,4) +org.eclipse.persistence.internal.security=[3.0,4) +org.eclipse.persistence.internal.sessions=[3.0,4) + +org.eclipse.persistence.annotations=[3.0,4) +org.eclipse.persistence.descriptors=[3.0,4) +org.eclipse.persistence.descriptors.changetracking=[3.0,4) +org.eclipse.persistence.queries=[3.0,4) +org.eclipse.persistence.indirection=[3.0,4) +org.eclipse.persistence.internal.descriptors=[3.0,4) +org.eclipse.persistence.internal.identitymaps=[3.0,4) +org.eclipse.persistence.internal.jpa=[3.0,4) +org.eclipse.persistence.internal.jpa.rs.metadata.model=[3.0,4) +org.eclipse.persistence.internal.weaving=[3.0,4) +org.eclipse.persistence.jpa=[3.0,4) +org.eclipse.persistence.platform.server.was=[3.0,4) +org.eclipse.persistence.internal.sessions.cdi=[3.0,4) +org.eclipse.persistence.platform.database=[3.0,4) +org.eclipse.persistence.sessions=[3.0,4) +org.eclipse.persistence.tools.schemaframework=[3.0,4) +org.eclipse.persistence.transaction=[3.0,4) diff --git a/settings.gradle b/settings.gradle index 54000713c5..ca6903e25c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -87,9 +87,17 @@ logger.lifecycle "Java versions for main code: " + gradle.ext.javaVersions.main logger.lifecycle "Java versions for tests: " + gradle.ext.javaVersions.test include 'hibernate-core' +include 'hibernate-core-jakarta' include 'hibernate-entitymanager' include 'hibernate-testing' +include 'hibernate-testing-jakarta' +// todo (jakarta): remove these three when the jakarta artifacts are released +include 'hibernate-jboss-jta' +include 'hibernate-transaction-client' +include 'hibernate-transaction-spi' + include 'hibernate-envers' +include 'hibernate-envers-jakarta' include 'hibernate-spatial' include 'hibernate-java8' @@ -127,6 +135,10 @@ include 'metamodel-generator' project(':metamodel-generator').projectDir = new File(rootProject.projectDir, "tooling/metamodel-generator") project(':metamodel-generator').name = 'hibernate-jpamodelgen' +include 'metamodel-generator-jakarta' +project(':metamodel-generator-jakarta').projectDir = new File(rootProject.projectDir, "tooling/metamodel-generator-jakarta") +project(':metamodel-generator-jakarta').name = 'hibernate-jpamodelgen-jakarta' + include 'hibernate-gradle-plugin' project(':hibernate-gradle-plugin').projectDir = new File(rootProject.projectDir, "tooling/hibernate-gradle-plugin") diff --git a/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle b/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle new file mode 100644 index 0000000000..13d32b6685 --- /dev/null +++ b/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Annotation Processor to generate JPA 3 static metamodel classes' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + // JAXB + compile( libraries.jakarta_jaxb_api ) + compile( libraries.jakarta_jaxb_runtime ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile fileTree(dir: 'libs', include: '*.jar') +} + +jar { + mustRunAfter project(':hibernate-jpamodelgen').tasks.jar + dependsOn project(':hibernate-jpamodelgen').tasks.jar + def baseDir = project(':hibernate-jpamodelgen').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-jpamodelgen', 'hibernate-jpamodelgen-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-direct-modelgen.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java index 245c9e3111..e97bfe3067 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java @@ -199,7 +199,7 @@ public final class ClassWriter { private static String writeGeneratedAnnotation(MetaEntity entity, Context context) { StringBuilder generatedAnnotation = new StringBuilder(); generatedAnnotation.append( "@" ) - .append( entity.importType( context.getGeneratedAnnotation().getQualifiedName().toString() ) ) + .append( entity.importType( context.getGeneratedAnnotationFqcn() ) ) .append( "(value = \"" ) .append( JPAMetaModelEntityProcessor.class.getName() ); if ( context.addGeneratedDate() ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java index da0d9a6f55..c09ec34288 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -50,7 +50,7 @@ public final class Context { private final boolean lazyXmlParsing; private final String persistenceXmlLocation; private final List ormXmlFiles; - private final TypeElement generatedAnnotation; + private final String generatedAnnotation; /** * Whether all mapping files are xml-mapping-metadata-complete. In this case no annotation processing will take @@ -96,14 +96,16 @@ public final class Context { lazyXmlParsing = Boolean.parseBoolean( pe.getOptions().get( JPAMetaModelEntityProcessor.LAZY_XML_PARSING ) ); logDebug = Boolean.parseBoolean( pe.getOptions().get( JPAMetaModelEntityProcessor.DEBUG_OPTION ) ); + // Workaround that Eclipse transformer tries to replace this constant which we don't want + String j = "j"; TypeElement java8AndBelowGeneratedAnnotation = - pe.getElementUtils().getTypeElement( "javax.annotation.Generated" ); + pe.getElementUtils().getTypeElement( j + "avax.annotation.Generated" ); if ( java8AndBelowGeneratedAnnotation != null ) { - generatedAnnotation = java8AndBelowGeneratedAnnotation; + generatedAnnotation = java8AndBelowGeneratedAnnotation.getQualifiedName().toString(); } else { // Using the new name for this annotation in Java 9 and above - generatedAnnotation = pe.getElementUtils().getTypeElement( "javax.annotation.processing.Generated" ); + generatedAnnotation = "javax.annotation.processing.Generated"; } } @@ -115,7 +117,7 @@ public final class Context { return addGeneratedAnnotation; } - public TypeElement getGeneratedAnnotation() { + public String getGeneratedAnnotationFqcn() { return generatedAnnotation; } From c29b2d27ee66b0da2af2a640b5c2179c6454a983 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 23 Apr 2021 12:07:20 +0200 Subject: [PATCH 04/45] HHH-14577 Add Jenkinsfiles for running TCKs --- ci/jpa-2.2-tck.Jenkinsfile | 72 +++++++ ci/jpa-3.0-tck.Jenkinsfile | 72 +++++++ gradle/libraries.gradle | 1 + .../hibernate-core-jakarta.gradle | 179 +++++++++--------- .../hibernate-envers-jakarta.gradle | 58 +++--- .../hibernate-jboss-jta.gradle | 10 +- .../hibernate-testing-jakarta.gradle | 16 +- .../hibernate-transaction-client.gradle | 8 +- .../hibernate-transaction-spi.gradle | 62 ------ settings.gradle | 8 +- 10 files changed, 295 insertions(+), 191 deletions(-) create mode 100644 ci/jpa-2.2-tck.Jenkinsfile create mode 100644 ci/jpa-3.0-tck.Jenkinsfile delete mode 100644 hibernate-transaction-spi/hibernate-transaction-spi.gradle diff --git a/ci/jpa-2.2-tck.Jenkinsfile b/ci/jpa-2.2-tck.Jenkinsfile new file mode 100644 index 0000000000..fbc97668e0 --- /dev/null +++ b/ci/jpa-2.2-tck.Jenkinsfile @@ -0,0 +1,72 @@ +@Library('hibernate-jenkins-pipeline-helpers@1.5') _ + +pipeline { + agent { + label 'LongDuration' + } + tools { + jdk 'OpenJDK 8 Latest' + } + stages { + stage('Build') { + steps { + script { + docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') { + docker.image('openjdk:8-jdk').pull() + } + } + dir('hibernate') { + checkout scm + sh """ \ + ./gradlew publishToMavenLocal + """ + script { + env.HIBERNATE_VERSION = sh ( + script: "grep hibernateVersion gradle/version.properties|cut -d'=' -f2", + returnStdout: true + ).trim() + } + } + dir('tck') { + checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/hibernate/jakarta-tck-runner.git']]] + sh """ \ + cd jpa-2.2; docker build -t jakarta-tck-runner . + """ + } + } + } + stage('Run TCK') { + steps { + sh """ \ + docker rm -f tck + docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -e NO_SLEEP=true -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner + docker cp tck:/tck/persistence-tck/tmp/JTreport/ ./JTreport + """ + archiveArtifacts artifacts: 'JTreport/**' + script { + failures = sh ( + script: """ \ + while read line; do + if [[ "$line" != "*Passed." ]]; then + echo "$line" + fi + done = 9 ) { - // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set - jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) - // Weld needs this to generate proxies - jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) - jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) - } -} \ No newline at end of file +// todo: enable again when we can finally use the Jakarta JARs from narayana +//task unpackTestJar(type: Copy) { +// dependsOn jar +// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { +// def outputDir = file("${buildDir}/unpacked/" + it.name) +// from zipTree(it) +// into outputDir +// } +//} +// +//task copyBundleResources (type: Copy) { +// dependsOn unpackTestJar +// File unpackedDir = new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") +// ext { +// bundlesTargetDir = file( "${buildDir}/bundles" ) +// bundleTokens = dbBundle[db] +// ext.bundleTokens['buildDirName'] = buildDir.absolutePath +// } +// +// from file("${buildDir}/unpacked/${unpackedDir.name}/templates") +// into ext.bundlesTargetDir +// filter( ReplaceTokens, tokens: ext.bundleTokens) +// doFirst { +// ext.bundlesTargetDir.mkdirs() +// } +//} +// +//processTestResources.dependsOn copyBundleResources +// +//artifacts { +// tests new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") +//} +// +//test { +// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { +// def outputDir = file("${buildDir}/unpacked/" + it.name) +// testClassesDirs += files(outputDir) +// classpath += files(outputDir) +// } +// systemProperty 'file.encoding', 'utf-8' +// +// if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { +// // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set +// jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) +// // Weld needs this to generate proxies +// jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) +// jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) +// } +//} \ No newline at end of file diff --git a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle index 66f4b74493..ac4963b0b4 100644 --- a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle +++ b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle @@ -28,9 +28,10 @@ dependencies { 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' - testCompile( project( ':hibernate-testing-jakarta' ) ) testCompile( project( ':hibernate-envers-jakarta' ) ) - testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) +// todo: enable again when we can finally use the Jakarta JARs from narayana +// testCompile( project( ':hibernate-testing-jakarta' ) ) +// testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) } jar { @@ -75,29 +76,30 @@ jar { } } -task unpackTestJar(type: Copy) { - dependsOn jar - fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { - def outputDir = file("${buildDir}/unpacked/" + it.name) - from zipTree(it) - into outputDir - } -} - -test { - dependsOn unpackTestJar - fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { - def outputDir = file("${buildDir}/unpacked/" + it.name) - testClassesDirs += files(outputDir) - classpath += files(outputDir) - } - systemProperty 'file.encoding', 'utf-8' - - if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { - // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set - jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) - // Weld needs this to generate proxies - jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) - jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) - } -} \ No newline at end of file +// todo: enable again when we can finally use the Jakarta JARs from narayana +//task unpackTestJar(type: Copy) { +// dependsOn jar +// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { +// def outputDir = file("${buildDir}/unpacked/" + it.name) +// from zipTree(it) +// into outputDir +// } +//} +// +//test { +// dependsOn unpackTestJar +// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { +// def outputDir = file("${buildDir}/unpacked/" + it.name) +// testClassesDirs += files(outputDir) +// classpath += files(outputDir) +// } +// systemProperty 'file.encoding', 'utf-8' +// +// if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { +// // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set +// jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) +// // Weld needs this to generate proxies +// jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) +// jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) +// } +//} \ No newline at end of file diff --git a/hibernate-jboss-jta/hibernate-jboss-jta.gradle b/hibernate-jboss-jta/hibernate-jboss-jta.gradle index e0331957af..bc3ebb694f 100644 --- a/hibernate-jboss-jta/hibernate-jboss-jta.gradle +++ b/hibernate-jboss-jta/hibernate-jboss-jta.gradle @@ -7,7 +7,13 @@ description = 'JBoss JTA transformed to be JTA 2.0 compatible' -apply from: rootProject.file( 'gradle/java-module.gradle' ) +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +tasks.withType(PublishToMavenRepository) { + onlyIf { + repository == publishing.repositories.mavenLocal + } +} configurations { jakartaeeTransformJars @@ -16,7 +22,7 @@ configurations { dependencies { compile( libraries.jakarta_jta ) compile( libraries.jakarta_resource ) - compile( project(':hibernate-transaction-spi') ) + compile( libraries.jboss_tx_spi_jakarta ) jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', 'commons-cli:commons-cli:1.4', diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle index 34aa2bed41..a018244827 100644 --- a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -7,9 +7,13 @@ description = 'Support for testing Hibernate ORM Jakarta functionality' -// todo (jakarta): replace this when the jakarta artifact is released -apply from: rootProject.file( 'gradle/java-module.gradle' ) -//apply from: rootProject.file( 'gradle/published-java-module.gradle' ) +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +tasks.withType(PublishToMavenRepository) { + onlyIf { + repository == publishing.repositories.mavenLocal + } +} configurations { jakartaeeTransformJars @@ -26,9 +30,9 @@ dependencies { compile( libraries.log4j ) // todo (jakarta): replace this when the jakarta artifacts are released compile project( ':hibernate-jboss-jta' ) -// compile( libraries.jboss_tx_spi_jakarta ) { -// transitive=false; -// } + compile( libraries.jboss_tx_spi_jakarta ) { + transitive=false; + } // compile ( libraries.jboss_jta_jakarta ) { // transitive=false; // } diff --git a/hibernate-transaction-client/hibernate-transaction-client.gradle b/hibernate-transaction-client/hibernate-transaction-client.gradle index bd3cb0430b..591d8367ea 100644 --- a/hibernate-transaction-client/hibernate-transaction-client.gradle +++ b/hibernate-transaction-client/hibernate-transaction-client.gradle @@ -7,7 +7,13 @@ description = 'Wildfly Transaction Client transformed to be JTA 2.0 compatible' -apply from: rootProject.file( 'gradle/java-module.gradle' ) +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +tasks.withType(PublishToMavenRepository) { + onlyIf { + repository == publishing.repositories.mavenLocal + } +} configurations { jakartaeeTransformJars diff --git a/hibernate-transaction-spi/hibernate-transaction-spi.gradle b/hibernate-transaction-spi/hibernate-transaction-spi.gradle deleted file mode 100644 index 57aced585f..0000000000 --- a/hibernate-transaction-spi/hibernate-transaction-spi.gradle +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ - -description = 'Wildfly Transaction SPI transformed to be JTA 2.0 compatible' - -apply from: rootProject.file( 'gradle/java-module.gradle' ) - -configurations { - jakartaeeTransformJars -} - -dependencies { - compile( libraries.jakarta_jta ) - - jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', - 'commons-cli:commons-cli:1.4', - 'org.slf4j:slf4j-simple:1.7.30', - 'org.slf4j:slf4j-api:1.7.26', - 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', - 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' - testCompile ( libraries.jboss_tx_spi ) { - transitive=false; - } -} - -jar { - def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("jboss-transaction-spi-") } - inputs.files(sourceJarPath).skipWhenEmpty() - outputs.dir project.buildDir - doLast { - new File(project.buildDir, "libs").mkdirs() - fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } - - println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' - - def finalBundleJarName = project.buildDir.path + '/libs/hibernate-transaction-spi-' + project.version + ".jar" - println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' - - def transformerArgs = [ - sourceJarPath, finalBundleJarName, - '-q', // quiet output - '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, - '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, - '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, - ] - - println 'Transformer options:' - transformerArgs.each { - println ' [ ' + it + ' ]' - } - - javaexec { - classpath configurations.jakartaeeTransformJars - main = 'org.eclipse.transformer.jakarta.JakartaTransformer' - args = transformerArgs - } - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index ca6903e25c..af1d875e26 100644 --- a/settings.gradle +++ b/settings.gradle @@ -90,11 +90,11 @@ include 'hibernate-core' include 'hibernate-core-jakarta' include 'hibernate-entitymanager' include 'hibernate-testing' -include 'hibernate-testing-jakarta' +// todo: enable again when we can finally use the Jakarta JARs from narayana +//include 'hibernate-testing-jakarta' // todo (jakarta): remove these three when the jakarta artifacts are released -include 'hibernate-jboss-jta' -include 'hibernate-transaction-client' -include 'hibernate-transaction-spi' +//include 'hibernate-jboss-jta' +//include 'hibernate-transaction-client' include 'hibernate-envers' include 'hibernate-envers-jakarta' From 8dabefd11153b80bad79dbe10ca874003647e24a Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Thu, 22 Apr 2021 17:14:22 +0200 Subject: [PATCH 05/45] HHH-14573 Remove useless call to EnhancementAsProxyLazinessInterceptor#isInitialized() --- .../hibernate/engine/internal/AbstractEntityEntry.java | 4 +--- .../java/org/hibernate/event/internal/WrapVisitor.java | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java index c203ce2506..cfa74558ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java @@ -355,9 +355,7 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry { if ( enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames() ) { return false; } - // When a proxy has dirty attributes, we have to treat it like a normal entity to flush changes - return !enhancementAsProxyLazinessInterceptor.isInitialized() - || !persister.hasCollections() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes(); + return true; } } else if ( entity instanceof HibernateProxy ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java index a7e0389956..bf6193aaa3 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java @@ -15,7 +15,6 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLaziness import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptable; -import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.EventSource; import org.hibernate.internal.CoreLogging; @@ -109,11 +108,8 @@ public class WrapVisitor extends ProxyVisitor { } else { if ( entity instanceof PersistentAttributeInterceptable ) { - final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); - if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) { - if ( !( (EnhancementAsProxyLazinessInterceptor) interceptor ).isInitialized() ) { - return null; - } + if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) { + return null; } } From 996debdc5410992fdfbbce5cf57492f4db69a367 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 30 Apr 2021 12:24:18 +0000 Subject: [PATCH 06/45] 5.5.0.Alpha1 --- changelog.txt | 58 +++++++++++++++++++++++++++++++++++++++ gradle/version.properties | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index e9aed989b0..3d8548993b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,64 @@ Hibernate 5 Changelog Note: Please refer to JIRA to learn more about each issue. +Changes in 5.5.0.Alpha1 (April 30, 2021) +------------------------------------------------------------------------------------------------------------------------ + +https://hibernate.atlassian.net/projects/HHH/versions/31844 + +** Bug + * [HHH-14571] - Hibernate.isPropertyInitialized( someEntity, "id" ) returns false + * [HHH-14567] - Filters are ignored if enabled after query creation but before execution + * [HHH-14557] - Connection leaked on rollback with mode DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION + * [HHH-14549] - Collection with default field initializer will always be empty + * [HHH-14537] - EntityNotFoundException thrown when non-existing association with @NotFound(IGNORE) mapped has proxy in PersistenceContext + * [HHH-14523] - Spatial Update Z axis of a org.locationtech.jts.geom.Point on Postgis + * [HHH-14475] - select indices from ternary relation is broken since 5.4.13 + * [HHH-14471] - Concurrency issue in DynamicBatchingEntityLoader + * [HHH-14467] - AnnotationException: A Foreign key refering from has the wrong number of column. should be 0 + * [HHH-14466] - StackOverflowError loading an entity with eager one-to-many if bidirectional and many-to-one side is the ID + * [HHH-14460] - NPE when setter is missing for persistent property + * [HHH-14449] - ResultStream closing is not properly handled + * [HHH-14445] - Javassist skip EntityWithMutableAttributesTest, LoadAndUpdateEntitiesWithCollectionsTest, SimpleDynamicUpdateTest, SimpleDynamicUpdateTest + * [HHH-14439] - QueryException: Unrecognized parameter label when executing the same query with subselects twice with different list parameters + * [HHH-14424] - When enhanced as a proxy with dirty checking is enabled, on flush uninitialized entities containing collections are updated setting all fields to null + * [HHH-14408] - SPI provided user types are not applied + * [HHH-14407] - NPE in Column.getSqlTypeCode(Mapping mapping) for column 'hib_sess_id' when using PersistentTableBulkIdStrategy + * [HHH-14404] - SessionBuilder.connectionHandlingMode is ignored + * [HHH-14390] - StackOverflowError with @Fetch(FetchMode.SELECT) mapped for entity with an ID that is a bidirectional one-to-one eager association + * [HHH-14389] - Add test case that throw IllegalArgumentException using EntityManager#find by ID when ID is a one-to-one association + * [HHH-14386] - Persistence.createEntityManagerFactory("testPU") fails, if persistence unit has config & CurrentTenantIdentifierResolver is not null. + * [HHH-14384] - Fix QueryProducer.createNativeQuery documentation + * [HHH-14380] - Join ordering logic wrongly pushes cross joins from subqueries to parent + * [HHH-14364] - UpdateDetachedTest#testUpdateDetachedWithAttachedPersistentSet failing when run on OracleDB + * [HHH-14363] - MutableTypeEnhancementTestCase failing when run on Oracle DB + * [HHH-14360] - NullPointerException on AbstractEntityPersister.resolveDirtyAttributeIndexes + * [HHH-14355] - NPE in Envers AdditionalJaxbMappingProducerImpl when XML mapping is disabled + * [HHH-14351] - Broken order by type + * [HHH-14350] - MariaDB103Dialect requires the lock wait timeout to be expressed in seconds + * [HHH-14348] - Lazy collection is fetched during dirty checking with bytecode enhancement + * [HHH-14346] - org.hibernate.metamodel.model.domain.internal.AbstractManagedType#getPluralAttributes NPE + * [HHH-14343] - Nested ID classes fail with AnnotationException: Column name game_id of x.x.PlayerStat not found in JoinColumns.referencedColumnName + * [HHH-14335] - Cache resolution of SimpleValue#getType + * [HHH-14333] - Pessimistic Lock causes FOR UPDATE on outer join statements + * [HHH-14329] - DirtinessTracker usage for enhanced entities doesn't respect mutable types + * [HHH-14322] - HBM many-to-one property-ref broken since 5.3.2 due to HHH-12684 + * [HHH-14319] - CollectionType#replaceElements may clear the original collection during merge + * [HHH-14317] - Avoid closing datasource in AgroalConnectionProvider if datasource is not initialized + * [HHH-14316] - Avoid accessing state in DriverManagerConnectionProviderImpl if null + * [HHH-14312] - Padded batch style entity loader ignores entity graph + * [HHH-14310] - Document hibernate.query.in_clause_parameter_padding + * [HHH-14288] - Complex batch insert query stopped to work + * [HHH-14279] - Broken 'with key(...)' operator on entity-key maps + * [HHH-14276] - Nested ID class using derived identifiers fails with strange AnnotationException: unable to find column reference in the @MapsId mapping: `game_id` + * [HHH-14275] - Broken link to Infinispan User Guide in Hibernate 5.3 User Guide + * [HHH-14264] - Entity graph cannot be applied to child class + * [HHH-14260] - Dead links in user guide + * [HHH-14257] - An Entity A with a map collection having as index an Embeddable with a an association to the Entity A fails with a NPE + * [HHH-14251] - Invalid SQL for @Embedded UPDATE + * [HHH-14249] - MultiLineImport fails when script contains blank spaces or tabs at the end of the last sql statement + + Changes in 5.4.14.Final (April 6, 2020) ------------------------------------------------------------------------------------------------------------------------ diff --git a/gradle/version.properties b/gradle/version.properties index 27307e6e59..f8f2cedadf 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file +hibernateVersion=5.5.0.Alpha1 \ No newline at end of file From 830423422d357bfe374bae54ed6db39c3fb0daf1 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 30 Apr 2021 12:30:04 +0000 Subject: [PATCH 07/45] 5.5.0-SNAPSHOT --- gradle/version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/version.properties b/gradle/version.properties index f8f2cedadf..27307e6e59 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0.Alpha1 \ No newline at end of file +hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file From 41c71bfed7d8eb74bd0574ed7bd2552d055dcf46 Mon Sep 17 00:00:00 2001 From: Emmanuel Duchastenier Date: Tue, 23 Mar 2021 17:37:35 +0100 Subject: [PATCH 08/45] HHH-13779 (5.4) - Foreign key schema migrator should be case-insensitive This avoids re-creating existing foreign keys with a different name, after migrating from Hibernate 4 to Hibernate 5 (as implicit naming convention has changed). Actually, some RDBMS allow it (PostgreSQL, MySQL, MS SQL Server, ...) and duplicate the same key, whereas others (Oracle, ...) do not allow it and Schema update fails. This fix ignores the case of the table and column name when checking if a equivalent Foreign Key already exists (whatever its name) Closes https://hibernate.atlassian.net/browse/HHH-13779 (cherry picked from commit 0b819863f2cee41c7067d7e3656356f0b1221ef1) --- .../internal/AbstractSchemaMigrator.java | 21 +++--- .../internal/AbstractSchemaMigratorTest.java | 73 +++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java index e38b3034b0..0f58cfee50 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java @@ -463,15 +463,7 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator { * Find existing keys based on referencing column and referencedTable. "referencedColumnName" is not checked * because that always is the primary key of the "referencedTable". */ - Predicate mappingPredicate = m -> { - String existingReferencingColumn = m.getReferencingColumnMetadata().getColumnIdentifier().getText(); - String existingReferencedTable = m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName(); - return referencingColumn.equals( existingReferencingColumn ) && referencedTable.equals( existingReferencedTable ); - }; - Stream keyStream = StreamSupport.stream( tableInformation.getForeignKeys().spliterator(), false ); - Stream mappingStream = keyStream.flatMap( k -> StreamSupport.stream( k.getColumnReferenceMappings().spliterator(), false ) ); - boolean found = mappingStream.anyMatch( mappingPredicate ); - if ( found ) { + if (equivalentForeignKeyExistsInDatabase(tableInformation, referencingColumn, referencedTable)) { return true; } @@ -480,6 +472,17 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator { return tableInformation.getForeignKey( Identifier.toIdentifier( foreignKey.getName() ) ) != null; } + boolean equivalentForeignKeyExistsInDatabase(TableInformation tableInformation, String referencingColumn, String referencedTable) { + Predicate mappingPredicate = m -> { + String existingReferencingColumn = m.getReferencingColumnMetadata().getColumnIdentifier().getText(); + String existingReferencedTable = m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName(); + return referencingColumn.equalsIgnoreCase( existingReferencingColumn ) && referencedTable.equalsIgnoreCase( existingReferencedTable ); + }; + Stream keyStream = StreamSupport.stream( tableInformation.getForeignKeys().spliterator(), false ); + Stream mappingStream = keyStream.flatMap( k -> StreamSupport.stream( k.getColumnReferenceMappings().spliterator(), false ) ); + return mappingStream.anyMatch( mappingPredicate ); + } + protected void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { final String exportIdentifier = exportable.getExportIdentifier(); if ( exportIdentifiers.contains( exportIdentifier ) ) { diff --git a/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java b/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java new file mode 100644 index 0000000000..8635fb788a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java @@ -0,0 +1,73 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.internal; + +import java.util.ArrayList; +import java.util.Set; + +import org.hibernate.boot.Metadata; +import org.hibernate.boot.model.TruthValue; +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.boot.model.relational.Namespace; +import org.hibernate.boot.model.relational.QualifiedTableName; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.internal.Formatter; +import org.hibernate.testing.TestForIssue; +import org.hibernate.tool.schema.extract.internal.ColumnInformationImpl; +import org.hibernate.tool.schema.extract.internal.ForeignKeyInformationImpl; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.internal.exec.GenerationTarget; +import org.hibernate.tool.schema.spi.ExecutionOptions; +import org.junit.Test; + +import static java.util.Collections.singletonList; +import static org.hamcrest.core.Is.is; +import static org.hibernate.boot.model.naming.Identifier.toIdentifier; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * @author Emmanuel Duchastenier + */ +public class AbstractSchemaMigratorTest { + + @Test + @TestForIssue(jiraKey = "HHH-13779") + public void testForeignKeyPreExistenceDetectionIgnoresCaseForTableAndColumnName() { + final AbstractSchemaMigrator schemaMigrator = new AbstractSchemaMigrator(null, null) { + @Override + protected NameSpaceTablesInformation performTablesMigration(Metadata metadata, DatabaseInformation existingDatabase, ExecutionOptions options, Dialect dialect, Formatter formatter, Set exportIdentifiers, boolean tryToCreateCatalogs, boolean tryToCreateSchemas, Set exportedCatalogs, Namespace namespace, GenerationTarget[] targets) { return null; } + }; + + final TableInformation existingTableInformation = mock(TableInformation.class); + final ArrayList columnReferenceMappings = new ArrayList<>(); + + final TableInformation destinationTableInformation = mock(TableInformation.class); + doReturn(new QualifiedTableName(toIdentifier("catalog"), toIdentifier("schema"), + toIdentifier("referenced_table"))) // Table name is lower case + .when(destinationTableInformation).getName(); + columnReferenceMappings.add(new ForeignKeyInformationImpl.ColumnReferenceMappingImpl( + new ColumnInformationImpl(null, toIdentifier("referencing_column"), // column name is lower case + 0, "typeName", 255, 0, TruthValue.TRUE), + new ColumnInformationImpl(destinationTableInformation, null, 1, "typeName", 0, 0, TruthValue.TRUE))); + doReturn(singletonList(new ForeignKeyInformationImpl(toIdentifier("FKp8mpamfw2inhj88hwhty1eipm"), columnReferenceMappings))) + .when(existingTableInformation).getForeignKeys(); + + final boolean existInDatabase = schemaMigrator.equivalentForeignKeyExistsInDatabase( + existingTableInformation, + "REFERENCING_COLUMN", "REFERENCED_TABLE"); // Table and column names are UPPER-case here, to prove the test + + assertThat("Expected ForeignKey pre-existence check to be case-insensitive", + existInDatabase, + is(true)); + } + +} \ No newline at end of file From 7144af5990ca4a11abbafeff26a1ad957ad08d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 3 May 2021 17:50:38 +0200 Subject: [PATCH 09/45] HHH-12445 Auto-detect when discriminator columns are nullable --- .../DiscriminatorNotNullSingleTableTest.java | 6 --- .../org/hibernate/cfg/AnnotationBinder.java | 4 +- .../cfg/annotations/EntityBinder.java | 1 + ...NullableDiscriminatorColumnSecondPass.java | 53 +++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java diff --git a/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java b/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java index 2c3bbf9ef3..16a503ef57 100644 --- a/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java @@ -45,12 +45,6 @@ public class DiscriminatorNotNullSingleTableTest extends BaseEntityManagerFuncti @Test public void test() { doInJPA( this::entityManagerFactory, entityManager -> { - entityManager.unwrap( Session.class ).doWork( connection -> { - try(Statement statement = connection.createStatement()) { - statement.executeUpdate( "ALTER TABLE Account ALTER COLUMN DTYPE SET NULL" ); - } - } ); - //tag::entity-inheritance-single-table-discriminator-value-persist-example[] DebitAccount debitAccount = new DebitAccount(); debitAccount.setId( 1L ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index a1e0f7c779..344b1e234c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -8,7 +8,6 @@ package org.hibernate.cfg; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; @@ -146,6 +145,7 @@ import org.hibernate.cfg.annotations.PropertyBinder; import org.hibernate.cfg.annotations.QueryBinder; import org.hibernate.cfg.annotations.SimpleValueBinder; import org.hibernate.cfg.annotations.TableBinder; +import org.hibernate.cfg.internal.NullableDiscriminatorColumnSecondPass; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.id.PersistentIdentifierGenerator; @@ -1484,6 +1484,8 @@ public final class AnnotationBinder { if ( LOG.isTraceEnabled() ) { LOG.tracev( "Setting discriminator for entity {0}", rootClass.getEntityName() ); } + context.getMetadataCollector().addSecondPass( + new NullableDiscriminatorColumnSecondPass( rootClass.getEntityName() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java index ff12ec196c..b8a23e596e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java @@ -71,6 +71,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.cfg.AccessType; import org.hibernate.cfg.AnnotationBinder; import org.hibernate.cfg.BinderHelper; +import org.hibernate.cfg.Ejb3DiscriminatorColumn; import org.hibernate.cfg.Ejb3JoinColumn; import org.hibernate.cfg.InheritanceState; import org.hibernate.cfg.ObjectNameSource; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java new file mode 100644 index 0000000000..989b8604cb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.cfg.internal; + +import java.util.Iterator; +import java.util.Map; + +import org.hibernate.MappingException; +import org.hibernate.cfg.SecondPass; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Selectable; + +public class NullableDiscriminatorColumnSecondPass implements SecondPass { + private final String rootEntityName; + + public NullableDiscriminatorColumnSecondPass(String rootEntityName) { + this.rootEntityName = rootEntityName; + } + + @Override + @SuppressWarnings("rawtypes") + public void doSecondPass(Map persistentClasses) throws MappingException { + PersistentClass rootPersistenceClass = (PersistentClass) persistentClasses.get( rootEntityName ); + if ( hasNullDiscriminatorValue( rootPersistenceClass ) ) { + for ( Iterator iterator = rootPersistenceClass.getDiscriminator().getColumnIterator(); + iterator.hasNext(); ) { + Selectable selectable = iterator.next(); + if ( selectable instanceof Column ) { + ( (Column) selectable ).setNullable( true ); + } + } + } + } + + @SuppressWarnings({ "unchecked" }) + private boolean hasNullDiscriminatorValue(PersistentClass rootPersistenceClass) { + if ( rootPersistenceClass.isDiscriminatorValueNull() ) { + return true; + } + Iterator subclassIterator = rootPersistenceClass.getSubclassIterator(); + while ( subclassIterator.hasNext() ) { + if ( subclassIterator.next().isDiscriminatorValueNull() ) { + return true; + } + } + return false; + } +} From 1a2510df1604b9e8be10f543e2ea8f78f51768f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 3 May 2021 18:11:29 +0200 Subject: [PATCH 10/45] HHH-12445 Fix ORM not detecting "null"/"not null" discriminator values correctly for joined inheritance --- .../entity/JoinedSubclassEntityPersister.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 8fb6279467..862e91419c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -106,7 +106,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { // subclass discrimination works by assigning particular // values to certain combinations of null primary key // values in the outer join using an SQL CASE - private final Map subclassesByDiscriminatorValue = new HashMap(); + private final Map subclassesByDiscriminatorValue = new HashMap<>(); private final String[] discriminatorValues; private final String[] notNullColumnNames; private final int[] notNullColumnTableNumbers; @@ -801,7 +801,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } public String getSubclassForDiscriminatorValue(Object value) { - return (String) subclassesByDiscriminatorValue.get( value ); + if ( value == null ) { + return subclassesByDiscriminatorValue.get( NULL_DISCRIMINATOR ); + } + else { + String result = subclassesByDiscriminatorValue.get( value ); + if ( result == null ) { + result = subclassesByDiscriminatorValue.get( NOT_NULL_DISCRIMINATOR ); + } + return result; + } } @Override From 662f86abe1c79c5e3fe9da86ee9d25cebd4beb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 3 May 2021 18:12:13 +0200 Subject: [PATCH 11/45] HHH-12445 Test "null"/"not-null" discriminator values --- ...ngleTableNullNotNullDiscriminatorTest.java | 112 +++++++++++++++++ .../JoinedNullNotNullDiscriminatorTest.java | 114 ++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java new file mode 100644 index 0000000000..71d48e40c6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java @@ -0,0 +1,112 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.inheritance.discriminator; + +import java.sql.Statement; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestForIssue(jiraKey = "HHH-12445") +public class SingleTableNullNotNullDiscriminatorTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + RootEntity.class, + Val1Entity.class, + Val2Entity.class, + NotNullEntity.class + }; + } + + @Test + public void test() { + inTransaction( session -> { + Val1Entity val1 = new Val1Entity(); + val1.setId( 1L ); + + Val2Entity val2 = new Val2Entity(); + val2.setId( 2L ); + + RootEntity root = new RootEntity(); + root.setId( 3L ); + + session.persist( val1 ); + session.persist( val2 ); + session.persist( root ); + + session.doWork( connection -> { + try (Statement statement = connection.createStatement()) { + statement.executeUpdate( + "insert into root_ent (DTYPE, id) " + + "values ('other', 4)" + ); + } + } ); + } ); + + inTransaction( session -> { + Map entities = session.createQuery( + "select e from root_ent e", RootEntity.class ) + .getResultList() + .stream() + .collect( Collectors.toMap( RootEntity::getId, Function.identity() ) ); + + assertThat( entities ).extractingByKey( 1L ).isInstanceOf( Val1Entity.class ); + assertThat( entities ).extractingByKey( 2L ).isInstanceOf( Val2Entity.class ); + assertThat( entities ).extractingByKey( 3L ).isInstanceOf( RootEntity.class ); + assertThat( entities ).extractingByKey( 4L ).isInstanceOf( NotNullEntity.class ); + } ); + } + + @Entity(name = "root_ent") + @Inheritance(strategy = InheritanceType.SINGLE_TABLE) + @DiscriminatorValue("null") + public static class RootEntity { + + @Id + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity(name = "val1_ent") + @DiscriminatorValue("val1") + public static class Val1Entity extends RootEntity { + + } + + @Entity(name = "val2_ent") + @DiscriminatorValue("val2") + public static class Val2Entity extends RootEntity { + + } + + @Entity(name = "notnull_ent") + @DiscriminatorValue("not null") + public static class NotNullEntity extends RootEntity { + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java new file mode 100644 index 0000000000..495ab9fff4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.inheritance.discriminator.joinedsubclass; + +import java.sql.Statement; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestForIssue(jiraKey = "HHH-12445") +public class JoinedNullNotNullDiscriminatorTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + RootEntity.class, + Val1Entity.class, + Val2Entity.class, + NotNullEntity.class + }; + } + + @Test + public void test() { + inTransaction( session -> { + Val1Entity val1 = new Val1Entity(); + val1.setId( 1L ); + + Val2Entity val2 = new Val2Entity(); + val2.setId( 2L ); + + RootEntity root = new RootEntity(); + root.setId( 3L ); + + session.persist( val1 ); + session.persist( val2 ); + session.persist( root ); + + session.doWork( connection -> { + try (Statement statement = connection.createStatement()) { + statement.executeUpdate( + "insert into root_ent (DTYPE, id) " + + "values ('other', 4)" + ); + } + } ); + } ); + + inTransaction( session -> { + Map entities = session.createQuery( + "select e from root_ent e", RootEntity.class ) + .getResultList() + .stream() + .collect( Collectors.toMap( RootEntity::getId, Function.identity() ) ); + + assertThat( entities ).extractingByKey( 1L ).isInstanceOf( Val1Entity.class ); + assertThat( entities ).extractingByKey( 2L ).isInstanceOf( Val2Entity.class ); + assertThat( entities ).extractingByKey( 3L ).isInstanceOf( RootEntity.class ); + assertThat( entities ).extractingByKey( 4L ).isInstanceOf( NotNullEntity.class ); + } ); + } + + @Entity(name = "root_ent") + @Inheritance(strategy = InheritanceType.JOINED) + @DiscriminatorColumn() + @DiscriminatorValue("null") + public static class RootEntity { + + @Id + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity(name = "val1_ent") + @DiscriminatorValue("val1") + public static class Val1Entity extends RootEntity { + + } + + @Entity(name = "val2_ent") + @DiscriminatorValue("val2") + public static class Val2Entity extends RootEntity { + + } + + @Entity(name = "notnull_ent") + @DiscriminatorValue("not null") + public static class NotNullEntity extends RootEntity { + + } +} From 72f4a2f61017f1b45812874031ef7debff34fe9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 3 May 2021 18:13:16 +0200 Subject: [PATCH 12/45] HHH-12445 Remove unused constants related to "null"/"not-null" discriminator values --- .../persister/entity/JoinedSubclassEntityPersister.java | 2 -- .../hibernate/persister/entity/SingleTableEntityPersister.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 862e91419c..fa7f5cb30d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -62,8 +62,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { private static final String IMPLICIT_DISCRIMINATOR_ALIAS = "clazz_"; private static final Object NULL_DISCRIMINATOR = new MarkerObject(""); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject(""); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; // the class hierarchy structure private final int tableSpan; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 494ce3f243..566d8d5a49 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -114,8 +114,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private static final Object NULL_DISCRIMINATOR = new MarkerObject( "" ); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "" ); - private static final String NULL_STRING = "null"; - private static final String NOT_NULL_STRING = "not null"; //INITIALIZATION: From 129484557b3e92f2a59db6b41db107e2c78e6f41 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 5 May 2021 15:47:50 +0200 Subject: [PATCH 13/45] Re-include the temporary jakarta testing modules --- ci/jpa-2.2-tck.Jenkinsfile | 6 +++--- ci/jpa-3.0-tck.Jenkinsfile | 6 +++--- settings.gradle | 9 ++++----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ci/jpa-2.2-tck.Jenkinsfile b/ci/jpa-2.2-tck.Jenkinsfile index fbc97668e0..87e9aa7bab 100644 --- a/ci/jpa-2.2-tck.Jenkinsfile +++ b/ci/jpa-2.2-tck.Jenkinsfile @@ -38,7 +38,7 @@ pipeline { stage('Run TCK') { steps { sh """ \ - docker rm -f tck + docker rm -f tck || true docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -e NO_SLEEP=true -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner docker cp tck:/tck/persistence-tck/tmp/JTreport/ ./JTreport """ @@ -47,8 +47,8 @@ pipeline { failures = sh ( script: """ \ while read line; do - if [[ "$line" != "*Passed." ]]; then - echo "$line" + if [[ "\$line" != *"Passed." ]]; then + echo "\$line" fi done Date: Thu, 6 May 2021 07:16:32 +0200 Subject: [PATCH 14/45] Fix publishing related issues in jakarta artifacts --- hibernate-jboss-jta/hibernate-jboss-jta.gradle | 2 +- hibernate-testing-jakarta/hibernate-testing-jakarta.gradle | 2 +- .../hibernate-transaction-client.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hibernate-jboss-jta/hibernate-jboss-jta.gradle b/hibernate-jboss-jta/hibernate-jboss-jta.gradle index bc3ebb694f..e1b30ccbd2 100644 --- a/hibernate-jboss-jta/hibernate-jboss-jta.gradle +++ b/hibernate-jboss-jta/hibernate-jboss-jta.gradle @@ -11,7 +11,7 @@ apply from: rootProject.file( 'gradle/published-java-module.gradle' ) tasks.withType(PublishToMavenRepository) { onlyIf { - repository == publishing.repositories.mavenLocal + repository.name == "MavenLocal" } } diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle index a018244827..10e119aab0 100644 --- a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -11,7 +11,7 @@ apply from: rootProject.file( 'gradle/published-java-module.gradle' ) tasks.withType(PublishToMavenRepository) { onlyIf { - repository == publishing.repositories.mavenLocal + repository.name == "MavenLocal" } } diff --git a/hibernate-transaction-client/hibernate-transaction-client.gradle b/hibernate-transaction-client/hibernate-transaction-client.gradle index 591d8367ea..2341fccede 100644 --- a/hibernate-transaction-client/hibernate-transaction-client.gradle +++ b/hibernate-transaction-client/hibernate-transaction-client.gradle @@ -11,7 +11,7 @@ apply from: rootProject.file( 'gradle/published-java-module.gradle' ) tasks.withType(PublishToMavenRepository) { onlyIf { - repository == publishing.repositories.mavenLocal + repository.name == "MavenLocal" } } From 0750c6784e6d92b8900b18d942d3faf7a4ba90cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 7 May 2021 08:37:02 +0200 Subject: [PATCH 15/45] Only apply --add-opens to compiler JVM options when using JDK9+ --- gradle.properties | 3 +-- gradle/java-module.gradle | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b8ec248b50..a20f3a1cb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ # Keep all these properties in sync unless you know what you are doing! org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 -# Needs add-opens because of https://github.com/gradle/gradle/issues/15538 -toolchain.compiler.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +toolchain.compiler.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 toolchain.javadoc.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 toolchain.launcher.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 diff --git a/gradle/java-module.gradle b/gradle/java-module.gradle index e3d60db623..85d5330adf 100644 --- a/gradle/java-module.gradle +++ b/gradle/java-module.gradle @@ -137,6 +137,8 @@ else { options.compilerArgs << gradle.ext.javaVersions.main.release.toString() } else { options.release = gradle.ext.javaVersions.main.release.asInt() + // Needs add-opens because of https://github.com/gradle/gradle/issues/15538 + options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] ) } } tasks.compileTestJava.configure { @@ -147,6 +149,8 @@ else { options.compilerArgs << gradle.ext.javaVersions.test.release.toString() } else { options.release = gradle.ext.javaVersions.test.release.asInt() + // Needs add-opens because of https://github.com/gradle/gradle/issues/15538 + options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] ) } } From a8f00b00aab67cfac886c7212dd94cb88eb0e14a Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 7 May 2021 09:50:35 +0200 Subject: [PATCH 16/45] Make use of narayana Jakarta artifacts --- gradle/libraries.gradle | 6 +- .../hibernate-core-jakarta.gradle | 180 +++++++++--------- .../hibernate-envers-jakarta.gradle | 58 +++--- .../hibernate-jboss-jta.gradle | 70 ------- .../hibernate-testing-jakarta.gradle | 8 +- settings.gradle | 2 - 6 files changed, 122 insertions(+), 202 deletions(-) delete mode 100644 hibernate-jboss-jta/hibernate-jboss-jta.gradle diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index 7c7f2e25e5..cf98d0a77b 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -141,10 +141,8 @@ ext { jodaTime: "joda-time:joda-time:${jodaTimeVersion}", informix: 'com.ibm.informix:jdbc:4.10.12', - jboss_jta: "org.jboss.narayana.jta:narayana-jta:5.11.1.Final", - // todo: update the version when the parent pom is published - jboss_tx_spi: "org.jboss:jboss-transaction-spi:7.6.0.Final", - // todo (jakarta): update the version when it is released + jboss_jta: "org.jboss.narayana.jta:narayana-jta:5.11.2.Final", + jboss_tx_spi: "org.jboss:jboss-transaction-spi:7.6.1.Final", jboss_jta_jakarta: "org.jboss.narayana.jta:narayana-jta-jakarta:5.11.2.Final", jboss_tx_spi_jakarta: "org.jboss:jboss-transaction-spi-jakarta:7.6.1.Final", xapool: "com.experlog:xapool:1.5.0", diff --git a/hibernate-core-jakarta/hibernate-core-jakarta.gradle b/hibernate-core-jakarta/hibernate-core-jakarta.gradle index c55a166042..6dbe272e27 100644 --- a/hibernate-core-jakarta/hibernate-core-jakarta.gradle +++ b/hibernate-core-jakarta/hibernate-core-jakarta.gradle @@ -48,48 +48,47 @@ dependencies { 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' -// todo: enable again when we can finally use the Jakarta JARs from narayana -// testCompile( project(':hibernate-testing-jakarta') ) -// testCompile fileTree(dir: 'libs', include: '*.jar') -// -// testCompile( libraries.shrinkwrap_api ) -// testCompile( libraries.shrinkwrap ) -// testCompile( libraries.jakarta_jacc ) -// testCompile( libraries.jakarta_validation ) -// testCompile( libraries.jandex ) -// testCompile( libraries.classmate ) -// testCompile( libraries.mockito ) -// testCompile( libraries.mockito_inline ) -// testCompile( libraries.jodaTime ) -// testCompile( libraries.assertj ) -// -// testCompile( libraries.jakarta_cdi ) -// -// testCompile( libraries.jakarta_validator ) { -// // for test runtime -// transitive = true -// } -// -// // for testing stored procedure support -// testCompile( libraries.derby ) -// -// testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final" ) -// testRuntime( libraries.jakarta_el ) -// testRuntime( 'jaxen:jaxen:1.1' ) -// testRuntime( libraries.javassist ) -// testRuntime( libraries.byteBuddy ) -// testRuntime( libraries.jakarta_weld ) -// testRuntime( libraries.atomikos ) -// testRuntime( libraries.atomikos_jta ) -//// todo (jakarta): replace this when the jakarta artifact is released -// testRuntime( project(':hibernate-transaction-client') ) -//// testRuntime( libraries.wildfly_transaction_client_jakarta ) -// -// testCompile libraries.shrinkwrap_descriptors_api_javaee -// testCompile libraries.shrinkwrap_descriptors_impl_javaee -// -// testCompile libraries.jboss_ejb_spec_jar -// testCompile libraries.jboss_annotation_spec_jar + testCompile( project(':hibernate-testing-jakarta') ) + testCompile fileTree(dir: 'libs', include: '*.jar') + + testCompile( libraries.shrinkwrap_api ) + testCompile( libraries.shrinkwrap ) + testCompile( libraries.jakarta_jacc ) + testCompile( libraries.jakarta_validation ) + testCompile( libraries.jandex ) + testCompile( libraries.classmate ) + testCompile( libraries.mockito ) + testCompile( libraries.mockito_inline ) + testCompile( libraries.jodaTime ) + testCompile( libraries.assertj ) + + testCompile( libraries.jakarta_cdi ) + + testCompile( libraries.jakarta_validator ) { + // for test runtime + transitive = true + } + + // for testing stored procedure support + testCompile( libraries.derby ) + + testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final" ) + testRuntime( libraries.jakarta_el ) + testRuntime( 'jaxen:jaxen:1.1' ) + testRuntime( libraries.javassist ) + testRuntime( libraries.byteBuddy ) + testRuntime( libraries.jakarta_weld ) + testRuntime( libraries.atomikos ) + testRuntime( libraries.atomikos_jta ) +// todo (jakarta): replace this when the jakarta artifact is released + testRuntime( project(':hibernate-transaction-client') ) +// testRuntime( libraries.wildfly_transaction_client_jakarta ) + + testCompile libraries.shrinkwrap_descriptors_api_javaee + testCompile libraries.shrinkwrap_descriptors_impl_javaee + + testCompile libraries.jboss_ejb_spec_jar + testCompile libraries.jboss_annotation_spec_jar } jar { @@ -134,52 +133,51 @@ jar { } } -// todo: enable again when we can finally use the Jakarta JARs from narayana -//task unpackTestJar(type: Copy) { -// dependsOn jar -// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { -// def outputDir = file("${buildDir}/unpacked/" + it.name) -// from zipTree(it) -// into outputDir -// } -//} -// -//task copyBundleResources (type: Copy) { -// dependsOn unpackTestJar -// File unpackedDir = new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") -// ext { -// bundlesTargetDir = file( "${buildDir}/bundles" ) -// bundleTokens = dbBundle[db] -// ext.bundleTokens['buildDirName'] = buildDir.absolutePath -// } -// -// from file("${buildDir}/unpacked/${unpackedDir.name}/templates") -// into ext.bundlesTargetDir -// filter( ReplaceTokens, tokens: ext.bundleTokens) -// doFirst { -// ext.bundlesTargetDir.mkdirs() -// } -//} -// -//processTestResources.dependsOn copyBundleResources -// -//artifacts { -// tests new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") -//} -// -//test { -// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { -// def outputDir = file("${buildDir}/unpacked/" + it.name) -// testClassesDirs += files(outputDir) -// classpath += files(outputDir) -// } -// systemProperty 'file.encoding', 'utf-8' -// -// if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { -// // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set -// jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) -// // Weld needs this to generate proxies -// jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) -// jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) -// } -//} \ No newline at end of file +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +task copyBundleResources (type: Copy) { + dependsOn unpackTestJar + File unpackedDir = new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") + ext { + bundlesTargetDir = file( "${buildDir}/bundles" ) + bundleTokens = dbBundle[db] + ext.bundleTokens['buildDirName'] = buildDir.absolutePath + } + + from file("${buildDir}/unpacked/${unpackedDir.name}/templates") + into ext.bundlesTargetDir + filter( ReplaceTokens, tokens: ext.bundleTokens) + doFirst { + ext.bundlesTargetDir.mkdirs() + } +} + +processTestResources.dependsOn copyBundleResources + +artifacts { + tests new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") +} + +test { + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle index ac4963b0b4..9e1e109c9f 100644 --- a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle +++ b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle @@ -29,9 +29,8 @@ dependencies { 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' testCompile( project( ':hibernate-envers-jakarta' ) ) -// todo: enable again when we can finally use the Jakarta JARs from narayana -// testCompile( project( ':hibernate-testing-jakarta' ) ) -// testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) + testCompile( project( ':hibernate-testing-jakarta' ) ) + testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) } jar { @@ -76,30 +75,29 @@ jar { } } -// todo: enable again when we can finally use the Jakarta JARs from narayana -//task unpackTestJar(type: Copy) { -// dependsOn jar -// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { -// def outputDir = file("${buildDir}/unpacked/" + it.name) -// from zipTree(it) -// into outputDir -// } -//} -// -//test { -// dependsOn unpackTestJar -// fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { -// def outputDir = file("${buildDir}/unpacked/" + it.name) -// testClassesDirs += files(outputDir) -// classpath += files(outputDir) -// } -// systemProperty 'file.encoding', 'utf-8' -// -// if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { -// // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set -// jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) -// // Weld needs this to generate proxies -// jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) -// jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) -// } -//} \ No newline at end of file +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +test { + dependsOn unpackTestJar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-jboss-jta/hibernate-jboss-jta.gradle b/hibernate-jboss-jta/hibernate-jboss-jta.gradle deleted file mode 100644 index e1b30ccbd2..0000000000 --- a/hibernate-jboss-jta/hibernate-jboss-jta.gradle +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ - -description = 'JBoss JTA transformed to be JTA 2.0 compatible' - -apply from: rootProject.file( 'gradle/published-java-module.gradle' ) - -tasks.withType(PublishToMavenRepository) { - onlyIf { - repository.name == "MavenLocal" - } -} - -configurations { - jakartaeeTransformJars -} - -dependencies { - compile( libraries.jakarta_jta ) - compile( libraries.jakarta_resource ) - compile( libraries.jboss_tx_spi_jakarta ) - - jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', - 'commons-cli:commons-cli:1.4', - 'org.slf4j:slf4j-simple:1.7.30', - 'org.slf4j:slf4j-api:1.7.26', - 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', - 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' - testCompile ( libraries.jboss_jta ) { - transitive=false; - } -} - -jar { - def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("narayana-jta-") } - inputs.files(sourceJarPath).skipWhenEmpty() - outputs.dir project.buildDir - doLast { - new File(project.buildDir, "libs").mkdirs() - fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } - - println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' - - def finalBundleJarName = project.buildDir.path + '/libs/hibernate-jboss-jta-' + project.version + ".jar" - println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' - - def transformerArgs = [ - sourceJarPath, finalBundleJarName, - '-q', // quiet output - '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, - '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, - '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, - ] - - println 'Transformer options:' - transformerArgs.each { - println ' [ ' + it + ' ]' - } - - javaexec { - classpath configurations.jakartaeeTransformJars - main = 'org.eclipse.transformer.jakarta.JakartaTransformer' - args = transformerArgs - } - } -} \ No newline at end of file diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle index 10e119aab0..7224a4a1d3 100644 --- a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -28,14 +28,12 @@ dependencies { compile( libraries.byteman_bmunit ) compile( libraries.xapool ) compile( libraries.log4j ) -// todo (jakarta): replace this when the jakarta artifacts are released - compile project( ':hibernate-jboss-jta' ) compile( libraries.jboss_tx_spi_jakarta ) { transitive=false; } -// compile ( libraries.jboss_jta_jakarta ) { -// transitive=false; -// } + compile ( libraries.jboss_jta_jakarta ) { + transitive=false; + } jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', 'commons-cli:commons-cli:1.4', diff --git a/settings.gradle b/settings.gradle index fc6fac4161..23d6def306 100644 --- a/settings.gradle +++ b/settings.gradle @@ -91,8 +91,6 @@ include 'hibernate-core-jakarta' include 'hibernate-entitymanager' include 'hibernate-testing' include 'hibernate-testing-jakarta' -// todo (jakarta): remove these two when the jakarta artifacts are released -include 'hibernate-jboss-jta' include 'hibernate-transaction-client' include 'hibernate-envers' From 0c79d1d644600b5d82614dc21e59e2930103025f Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 7 May 2021 12:16:02 +0200 Subject: [PATCH 17/45] Fix service registry injection through connection provider delegate --- .../org/hibernate/testing/jdbc/ConnectionProviderDelegate.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java index c301c66688..4044a71802 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java @@ -68,6 +68,9 @@ public class ConnectionProviderDelegate implements serviceRegistry ); } + if ( connectionProvider instanceof ServiceRegistryAwareService ) { + ( (ServiceRegistryAwareService) connectionProvider ).injectServices( serviceRegistry ); + } if ( connectionProvider instanceof Configurable ) { Configurable configurableConnectionProvider = (Configurable) connectionProvider; configurableConnectionProvider.configure( configurationValues ); From 51529f5f204a8b32f1196e521299feb7bc7052d1 Mon Sep 17 00:00:00 2001 From: mrizzi Date: Fri, 7 May 2021 17:50:09 +0200 Subject: [PATCH 18/45] HHH-14585 size() HQL function discards '@Where' clause --- .../hql/size/WhereClauseOrderBySizeTest.java | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java new file mode 100644 index 0000000000..81d7170b07 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java @@ -0,0 +1,195 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +package org.hibernate.test.hql.size; + +import org.hibernate.annotations.ResultCheckStyle; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.TestForIssue; +import org.junit.After; +import org.junit.Test; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.TypedQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; + +@TestForIssue(jiraKey = "HHH-14585") +public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class, Book.class }; + } + + @Test + public void testSizeAsOrderByExpression() { + doInJPA( + this::entityManagerFactory, + entityManager -> { + // initial situation: Alice has 1 book, Bob none + final Person alice = new Person( "Alice" ); + entityManager.persist( alice ); + + final Book book1 = new Book(); + book1.setOwner( alice ); + entityManager.persist( book1 ); + + final Person bob = new Person( "Bob" ); + entityManager.persist( bob ); + + final TypedQuery orderByBroken = entityManager.createQuery( + "SELECT p FROM Person p ORDER BY size(p.books) DESC", + Person.class + ); + final TypedQuery orderByWorking = entityManager.createQuery( + "SELECT p FROM Person p ORDER BY p.books.size DESC", + Person.class + ); + + List dbPeopleBroken = orderByBroken.getResultList(); + List dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + + // add 2 books to Bob + final Book book2 = new Book(); + book2.setOwner( bob ); + entityManager.persist( book2 ); + + final Book book3 = new Book(); + book3.setOwner( bob ); + entityManager.persist( book3 ); + + dbPeopleBroken = orderByBroken.getResultList(); + dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( bob, alice ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + + // remove (soft-deleting) both Bob's books + entityManager.remove( book2 ); + entityManager.remove( book3 ); + + // result lists are not equal anymore + dbPeopleBroken = orderByBroken.getResultList(); + dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + } + ); + } + + @After + public void cleanupDatabase() { + doInJPA( + this::entityManagerFactory, + entityManager -> { + for ( Book book : entityManager.createQuery( "from Book", Book.class ).getResultList() ) { + entityManager.remove( book ); + } + for ( Person person : entityManager.createQuery( "from Person", Person.class ).getResultList() ) { + entityManager.remove( person ); + } + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + @GeneratedValue + private Long id; + private String name; + @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + private List books = new ArrayList<>(); + + public Person(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + + @Override + public String toString() { + return "Person{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } + } + + @Entity(name = "Book") + @SQLDelete(sql = "UPDATE Book SET deleted = true WHERE id = ?", check = ResultCheckStyle.COUNT) + @Where(clause = "deleted = false") + public static class Book { + @Id + @GeneratedValue + private Long id; + private Boolean deleted = false; + @ManyToOne + private Person owner; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } + + public Person getOwner() { + return owner; + } + + public void setOwner(Person owner) { + this.owner = owner; + } + } +} From 15d9eb4112019389d16e2f560d9d0b2202d71ae8 Mon Sep 17 00:00:00 2001 From: Fabio Massimo Ercoli Date: Tue, 11 May 2021 09:05:28 +0200 Subject: [PATCH 19/45] HHH-14585 Skip test for some dialects --- .../hql/size/WhereClauseOrderBySizeTest.java | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java index 81d7170b07..f7baf77809 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java @@ -7,15 +7,12 @@ package org.hibernate.test.hql.size; -import org.hibernate.annotations.ResultCheckStyle; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.Where; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.hibernate.testing.TestForIssue; -import org.junit.After; -import org.junit.Test; +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -24,14 +21,21 @@ import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.TypedQuery; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; -import static org.junit.Assert.assertEquals; +import org.hibernate.annotations.ResultCheckStyle; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.PostgreSQL82Dialect; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; @TestForIssue(jiraKey = "HHH-14585") +@RequiresDialect(value = PostgreSQL82Dialect.class, comment = "Other databases may not support boolean data types") +@RequiresDialect(value = H2Dialect.class, comment = "Other databases may not support boolean data types") public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestCase { @Override @@ -96,21 +100,6 @@ public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestC ); } - @After - public void cleanupDatabase() { - doInJPA( - this::entityManagerFactory, - entityManager -> { - for ( Book book : entityManager.createQuery( "from Book", Book.class ).getResultList() ) { - entityManager.remove( book ); - } - for ( Person person : entityManager.createQuery( "from Person", Person.class ).getResultList() ) { - entityManager.remove( person ); - } - } - ); - } - @Entity(name = "Person") public static class Person { @Id @@ -120,6 +109,9 @@ public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestC @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private List books = new ArrayList<>(); + public Person() { + } + public Person(String name) { this.name = name; } From a106ce29dc7135357028454b6aba94459cc4bc3c Mon Sep 17 00:00:00 2001 From: Fabio Massimo Ercoli Date: Tue, 11 May 2021 09:06:56 +0200 Subject: [PATCH 20/45] HHH-14585 Handle filter fragment on CollectionSizeNode --- .../hibernate/hql/internal/ast/tree/CollectionSizeNode.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CollectionSizeNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CollectionSizeNode.java index b334e4b925..b630be5f91 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CollectionSizeNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/CollectionSizeNode.java @@ -12,6 +12,7 @@ import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; import org.hibernate.internal.util.StringHelper; import org.hibernate.persister.collection.CollectionPropertyMapping; import org.hibernate.persister.collection.CollectionPropertyNames; +import org.hibernate.persister.collection.OneToManyPersister; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.type.StandardBasicTypes; @@ -89,6 +90,8 @@ public class CollectionSizeNode extends SqlNode implements SelectExpression { buffer.append( ownerKeyColumns[i] ).append( " = " ).append( collectionKeyColumns[i] ); } + buffer.append( collectionDescriptor.filterFragment( collectionTableAlias, + collectionOwnerFromElement.getWalker().getEnabledFilters() ) ); buffer.append( ")" ); if ( scalarName != null ) { From d0febfd0427e2179cee03a6b9d8fe9321493d199 Mon Sep 17 00:00:00 2001 From: Fabio Massimo Ercoli Date: Tue, 11 May 2021 09:42:19 +0200 Subject: [PATCH 21/45] HHH-14585 Test more size() cases In particular projections using a size function --- .../hibernate/test/hql/size/filter/City.java | 60 ++++++++ .../test/hql/size/filter/Region.java | 49 +++++++ .../WhereAnnotatedOneToManySizeTest.java | 133 ++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java new file mode 100644 index 0000000000..c60400e547 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java @@ -0,0 +1,60 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.Where; + +@Entity +@Where(clause = "deleted = false") +public class City { + + @Id + private Integer id; + + private String name; + + @ManyToOne + private Region region; + + private Boolean deleted; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Region getRegion() { + return region; + } + + public void setRegion(Region region) { + this.region = region; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java new file mode 100644 index 0000000000..59da4d4f35 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java @@ -0,0 +1,49 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class Region { + + @Id + private Integer id; + + private String name; + + @OneToMany(mappedBy = "region") + private List cities = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getCities() { + return cities; + } + + public void setCities(List cities) { + this.cities = cities; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java new file mode 100644 index 0000000000..a5adb3af5b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java @@ -0,0 +1,133 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.hibernate.dialect.DB2Dialect; +import org.hibernate.query.spi.QueryImplementor; + +import org.hibernate.testing.SkipForDialect; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-14585") +public class WhereAnnotatedOneToManySizeTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Region.class, City.class }; + } + + @Before + public void before() { + Region lazio = new Region(); + lazio.setId( 1 ); + lazio.setName( "Lazio" ); + + Region lombardy = new Region(); + lombardy.setId( 2 ); + lombardy.setName( "Lombardy" ); + + City rome = new City(); + rome.setId( 1 ); + rome.setName( "Rome" ); + rome.setDeleted( false ); + rome.setRegion( lazio ); + + City gradoli = new City(); + gradoli.setId( 2 ); + gradoli.setName( "Gradoli" ); + gradoli.setDeleted( true ); + gradoli.setRegion( lazio ); + + City milan = new City(); + milan.setId( 3 ); + milan.setName( "Milan" ); + milan.setDeleted( false ); + milan.setRegion( lombardy ); + + City pavia = new City(); + pavia.setId( 4 ); + pavia.setName( "Pavia" ); + pavia.setDeleted( false ); + pavia.setRegion( lombardy ); + + lazio.getCities().add( rome ); + lazio.getCities().add( gradoli ); + + lombardy.getCities().add( milan ); + lombardy.getCities().add( pavia ); + + inTransaction( session -> { + session.persist( lazio ); + session.persist( lombardy ); + + session.persist( rome ); + session.persist( gradoli ); + session.persist( milan ); + session.persist( pavia ); + } ); + } + + @After + public void after() { + inTransaction( session -> { + session.createQuery( "DELETE FROM City c" ).executeUpdate(); + session.createQuery( "DELETE FROM Region c" ).executeUpdate(); + } ); + } + + @Test + @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + public void orderBy_sizeOf() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "select r, size(r.cities) from Region r order by size(r.cities) desc" ); + List result = query.getResultList(); + assertThat( result ).extracting( f -> f[0] ).extracting( "name" ).containsExactly( "Lombardy", "Lazio" ); + assertThat( result ).extracting( f -> f[1] ).containsExactly( 2, 1 ); + } ); + } + + @Test + @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + public void orderBy_dotSize() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "select r, r.cities.size from Region r order by r.cities.size desc" ); + List result = query.getResultList(); + assertThat( result ).extracting( f -> f[0] ).extracting( "name" ).containsExactly( "Lombardy", "Lazio" ); + assertThat( result ).extracting( f -> f[1] ).containsExactly( 2, 1 ); + } ); + } + + @Test + public void project_sizeOf() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "SELECT size(r.cities) FROM Region r", Integer.class ); + List cityCounts = query.getResultList(); + assertThat( cityCounts ).containsExactlyInAnyOrder( 1, 2 ); + } ); + } + + @Test + public void project_dotSize() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "SELECT r.cities.size FROM Region r", Integer.class ); + List cityCounts = query.getResultList(); + assertThat( cityCounts ).containsExactlyInAnyOrder( 1, 2 ); + } ); + } +} From b36b8e4d1c617c9b49be9be9450df2f60cbe1d30 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 12 May 2021 14:11:53 +0200 Subject: [PATCH 22/45] Enable publishing for hibernate-testing-jakarta --- .../hibernate-testing-jakarta.gradle | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle index 7224a4a1d3..716f96c9b0 100644 --- a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -9,12 +9,6 @@ description = 'Support for testing Hibernate ORM Jakarta functionality' apply from: rootProject.file( 'gradle/published-java-module.gradle' ) -tasks.withType(PublishToMavenRepository) { - onlyIf { - repository.name == "MavenLocal" - } -} - configurations { jakartaeeTransformJars } @@ -82,4 +76,4 @@ jar { } } } -} \ No newline at end of file +} From 7f152c36f7c70a1970a7d7d443076cc4a0a308ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 30 Apr 2021 14:32:41 +0200 Subject: [PATCH 23/45] HHH-14541 Test that the session factory is still open in SessionFactoryObserver#sessionFactoryClosing --- .../java/org/hibernate/test/events/CallbackTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java index 14e1e72a2e..5d37fa7a8c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java @@ -22,9 +22,11 @@ import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -33,6 +35,7 @@ import static org.junit.Assert.assertEquals; * * @author Steve Ebersole */ +@TestForIssue(jiraKey = {"HHH-2884", "HHH-10674", "HHH-14541"}) public class CallbackTest extends BaseCoreFunctionalTestCase { private TestingObserver observer = new TestingObserver(); private TestingListener listener = new TestingListener(); @@ -97,16 +100,22 @@ public class CallbackTest extends BaseCoreFunctionalTestCase { private int closedCount = 0; private int closingCount = 0; + @Override public void sessionFactoryCreated(SessionFactory factory) { + assertThat( factory.isClosed() ).isFalse(); creationCount++; } @Override public void sessionFactoryClosing(SessionFactory factory) { + // Test for HHH-14541 + assertThat( factory.isClosed() ).isFalse(); closingCount++; } + @Override public void sessionFactoryClosed(SessionFactory factory) { + assertThat( factory.isClosed() ).isTrue(); closedCount++; } } From eb4e397a048ca6013ac02c09c1ce4a834a65ad8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 30 Apr 2021 14:42:05 +0200 Subject: [PATCH 24/45] HHH-14541 Only mark the session factory as closed *after* SessionFactoryObserver#sessionFactoryClosing was called --- .../internal/SessionFactoryImpl.java | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 2c8bf16f09..17e3a258e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -160,7 +160,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { private final String name; private final String uuid; - private transient volatile boolean isClosed; + private transient volatile Status status = Status.OPEN; private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain(); @@ -535,7 +535,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } protected void validateNotClosed() { - if ( isClosed ) { + if ( Status.CLOSED == status ) { throw new IllegalStateException( "EntityManagerFactory is closed" ); } } @@ -625,7 +625,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } private Session buildEntityManager(final SynchronizationType synchronizationType, final Map map) { - assert !isClosed; + assert Status.CLOSED != status; SessionBuilderImplementor builder = withOptions(); if ( synchronizationType == SynchronizationType.SYNCHRONIZED ) { @@ -694,7 +694,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public boolean isOpen() { - return !isClosed; + return Status.CLOSED != status; } @Override @@ -789,9 +789,10 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { * collector release the memory. * @throws HibernateException */ + @Override public void close() throws HibernateException { synchronized (this) { - if ( isClosed ) { + if ( Status.OPEN != status ) { if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) { throw new IllegalStateException( "EntityManagerFactory is already closed" ); } @@ -800,40 +801,48 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return; } - isClosed = true; + status = Status.CLOSING; } - LOG.closing(); - observer.sessionFactoryClosing( this ); + try { + LOG.closing(); + observer.sessionFactoryClosing( this ); - settings.getMultiTableBulkIdStrategy().release( serviceRegistry.getService( JdbcServices.class ), buildLocalConnectionAccess() ); + settings.getMultiTableBulkIdStrategy().release( + serviceRegistry.getService( JdbcServices.class ), + buildLocalConnectionAccess() + ); - // NOTE : the null checks below handle cases where close is called from - // a failed attempt to create the SessionFactory + // NOTE : the null checks below handle cases where close is called from + // a failed attempt to create the SessionFactory - if ( cacheAccess != null ) { - cacheAccess.close(); + if ( cacheAccess != null ) { + cacheAccess.close(); + } + + if ( metamodel != null ) { + metamodel.close(); + } + + if ( queryPlanCache != null ) { + queryPlanCache.cleanup(); + } + + if ( delayedDropAction != null ) { + delayedDropAction.perform( serviceRegistry ); + } + + SessionFactoryRegistry.INSTANCE.removeSessionFactory( + getUuid(), + name, + settings.isSessionFactoryNameAlsoJndiName(), + serviceRegistry.getService( JndiService.class ) + ); } - - if ( metamodel != null ) { - metamodel.close(); + finally { + status = Status.CLOSED; } - if ( queryPlanCache != null ) { - queryPlanCache.cleanup(); - } - - if ( delayedDropAction != null ) { - delayedDropAction.perform( serviceRegistry ); - } - - SessionFactoryRegistry.INSTANCE.removeSessionFactory( - getUuid(), - name, - settings.isSessionFactoryNameAlsoJndiName(), - serviceRegistry.getService( JndiService.class ) - ); - observer.sessionFactoryClosed( this ); serviceRegistry.destroy(); } @@ -977,8 +986,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { getMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor) entityGraph ); } + @Override public boolean isClosed() { - return isClosed; + return Status.CLOSED == status; } private transient StatisticsImplementor statistics; @@ -1688,4 +1698,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return this.fastSessionServices; } + private enum Status { + OPEN, + CLOSING, + CLOSED; + } } From f7ab5f315dcdbe60310a347982671f031e6d88c8 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 12 May 2021 17:27:14 +0200 Subject: [PATCH 25/45] HHH-14541 Only mark the session factory as closed *after* SessionFactoryObserver#sessionFactoryClosing was called --- .../org/hibernate/internal/SessionFactoryImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 17e3a258e0..ef50a2b8ec 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -535,7 +535,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } protected void validateNotClosed() { - if ( Status.CLOSED == status ) { + if ( status == Status.CLOSED ) { throw new IllegalStateException( "EntityManagerFactory is closed" ); } } @@ -625,7 +625,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } private Session buildEntityManager(final SynchronizationType synchronizationType, final Map map) { - assert Status.CLOSED != status; + assert status != Status.CLOSED; SessionBuilderImplementor builder = withOptions(); if ( synchronizationType == SynchronizationType.SYNCHRONIZED ) { @@ -694,7 +694,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public boolean isOpen() { - return Status.CLOSED != status; + return status != Status.CLOSED; } @Override @@ -792,7 +792,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public void close() throws HibernateException { synchronized (this) { - if ( Status.OPEN != status ) { + if ( status != Status.OPEN ) { if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) { throw new IllegalStateException( "EntityManagerFactory is already closed" ); } @@ -988,7 +988,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public boolean isClosed() { - return Status.CLOSED == status; + return status == Status.CLOSED; } private transient StatisticsImplementor statistics; From 0dbffcc0685d83153e5ee33e3ba6eaa57cf24ead Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 12 May 2021 15:56:40 +0000 Subject: [PATCH 26/45] 5.5.0.Beta1 --- changelog.txt | 13 +++++++++++++ gradle/version.properties | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 3d8548993b..05f4fdf969 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,19 @@ Hibernate 5 Changelog Note: Please refer to JIRA to learn more about each issue. +Changes in 5.5.0.Beta1 (May 12, 2021) +------------------------------------------------------------------------------------------------------------------------ + +https://hibernate.atlassian.net/projects/HHH/versions/31938 + +** Bug + * [HHH-14541] - SessionFactoryObserver#sessionFactoryClosing() gets called after the session factory is marked as closed + * [HHH-13779] - Schema migrator should use case insensitive column comparison of foreign keys + +** Improvement + * [HHH-12445] - Discriminator column should be nullable when using @DiscriminatorValue( "null" ) + + Changes in 5.5.0.Alpha1 (April 30, 2021) ------------------------------------------------------------------------------------------------------------------------ diff --git a/gradle/version.properties b/gradle/version.properties index 27307e6e59..9277b6240d 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file +hibernateVersion=5.5.0.Beta1 \ No newline at end of file From 43539f0399636cf90b9f35d6c5efd807f37440f6 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 12 May 2021 16:03:47 +0000 Subject: [PATCH 27/45] 5.5.0-SNAPSHOT --- gradle/version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/version.properties b/gradle/version.properties index 9277b6240d..27307e6e59 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0.Beta1 \ No newline at end of file +hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file From 40851fc50da7edac397175dfc41a6d3a97adeb28 Mon Sep 17 00:00:00 2001 From: Nathan Xu Date: Wed, 13 Jan 2021 18:07:48 -0500 Subject: [PATCH 28/45] HHH-14406 fix Architecture svg image in user guide --- .../images/architecture/JPA_Hibernate.svg | 4443 +++++++---------- 1 file changed, 1936 insertions(+), 2507 deletions(-) diff --git a/documentation/src/main/asciidoc/userguide/images/architecture/JPA_Hibernate.svg b/documentation/src/main/asciidoc/userguide/images/architecture/JPA_Hibernate.svg index b6a240a85a..173e511352 100644 --- a/documentation/src/main/asciidoc/userguide/images/architecture/JPA_Hibernate.svg +++ b/documentation/src/main/asciidoc/userguide/images/architecture/JPA_Hibernate.svg @@ -1,2891 +1,2320 @@ - - - - image/svg+xml - - - - - - + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + fill-opacity="1" + stroke="black" + stroke-linecap="square" + width="885" + stroke-miterlimit="10" + stroke-opacity="1" + fill="black" + stroke-dasharray="none" + stroke-width="1" + height="438" + font-family="'Dialog'" + font-size="12" + stroke-dashoffset="0" + version="1.1" + id="svg699" +> + id="genericDefs"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id="g697"> + id="defs1"> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient5"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop23"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop25"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient6"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop28"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop30"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient7"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop33"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop35"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient8"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop38"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop40"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient9"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop43"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop45"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient10"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop48"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop50"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient13"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop63"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop65"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient14"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop68"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop70"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient15"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop73"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop75"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient16"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop78"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop80"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient17"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop83"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop85"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient18"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop88"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop90"/> - - - - - - - - - - - - - - - - - - - - - - - - - + + d="M-649 -37 L236 -37 L236 401 L-649 401 L-649 -37 Z" + id="path96"/> - + + d="M0 0 L0 37 L207 37 L207 0 Z" + id="path132"/> - + + d="M0 0 L0 35 L205 35 L205 0 Z" + id="path135"/> - + + d="M0 0 L0 33 L203 33 L203 0 Z" + id="path138"/> - + + d="M0 0 L0 25 L195 25 L195 0 Z" + id="path141"/> - + + d="M0 0 L0 37 L160 37 L160 0 Z" + id="path147"/> - + + d="M0 0 L0 35 L158 35 L158 0 Z" + id="path150"/> - + + d="M0 0 L0 33 L156 33 L156 0 Z" + id="path153"/> - + + d="M0 0 L0 25 L148 25 L148 0 Z" + id="path156"/> - + + d="M0 0 L0 37 L190 37 L190 0 Z" + id="path162"/> - + + d="M0 0 L0 35 L188 35 L188 0 Z" + id="path165"/> - + + d="M0 0 L0 33 L186 33 L186 0 Z" + id="path168"/> - + + d="M0 0 L0 25 L178 25 L178 0 Z" + id="path171"/> - + + d="M0 0 L0 37 L176 37 L176 0 Z" + id="path192"/> - + + d="M0 0 L0 35 L174 35 L174 0 Z" + id="path195"/> - + + d="M0 0 L0 33 L172 33 L172 0 Z" + id="path198"/> - + + d="M0 0 L0 25 L164 25 L164 0 Z" + id="path201"/> - + + d="M0 0 L0 37 L139 37 L139 0 Z" + id="path207"/> - + + d="M0 0 L0 35 L137 35 L137 0 Z" + id="path210"/> - + + d="M0 0 L0 33 L135 33 L135 0 Z" + id="path213"/> - + + d="M0 0 L0 25 L127 25 L127 0 Z" + id="path216"/> - + + d="M0 0 L0 37 L169 37 L169 0 Z" + id="path222"/> - + + d="M0 0 L0 35 L167 35 L167 0 Z" + id="path225"/> - + + d="M0 0 L0 33 L165 33 L165 0 Z" + id="path228"/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + d="M0 0 L0 25 L157 25 L157 0 Z" + id="path231"/> + fill="white" + transform="translate(649,37)" + stroke="white" + id="g237"/> + + x="2" + width="205" + height="1" + y="36" + clip-path="url(#clipPath14)" + stroke="none" + id="rect335"/> + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-627.5,104.5)" + stroke="rgb(232,232,232)" + id="g343"> - + x="0" + width="205" + height="35" + y="0" + clip-path="url(#clipPath15)" + stroke="none" + id="rect341"/> - - - + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-627.5,104.5)" + stroke="silver" + id="g347"> + d="M0 0 L205 0 L205 35 L0 35 L0 0 ZM1 1 L204 1 L204 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath15)" + stroke="none" + id="path345"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="rgb(232,232,232)" + id="g351"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect349"/> + fill="url(#linearGradient5)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="url(#linearGradient5)" + id="g355"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect353"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-622.5,109.5)" + id="g363"> + x="3" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image357" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image359" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityManager + x="47" + y="19" + clip-path="url(#clipPath17)" + stroke="none" + id="text361" + style="white-space: pre;">EntityManagerFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="rgb(232,232,232)" + id="g367"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect365"/> + fill="url(#linearGradient6)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="url(#linearGradient6)" + id="g371"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect369"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-622.5,109.5)" + id="g379"> + x="3" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image373" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image375" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityManager + x="47" + y="19" + clip-path="url(#clipPath17)" + stroke="none" + id="text377" + style="white-space: pre;">EntityManagerFactory + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-605,-16.5)" + stroke="gray" + id="g385"> + x="2" + width="158" + height="1" + y="36" + clip-path="url(#clipPath19)" + stroke="none" + id="rect381"/> + x="159" + width="1" + height="35" + y="2" + clip-path="url(#clipPath19)" + stroke="none" + id="rect383"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-604,-15.5)" + stroke="rgb(232,232,232)" + id="g389"> + x="0" + width="158" + height="35" + y="0" + clip-path="url(#clipPath20)" + stroke="none" + id="rect387"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-604,-15.5)" + stroke="silver" + id="g393"> + d="M0 0 L158 0 L158 35 L0 35 L0 0 ZM1 1 L157 1 L157 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath20)" + stroke="none" + id="path391"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="rgb(232,232,232)" + id="g397"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect395"/> + fill="url(#linearGradient7)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="url(#linearGradient7)" + id="g401"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect399"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-599,-10.5)" + id="g409"> + x="3" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image403" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image405" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Session + x="47" + y="19" + clip-path="url(#clipPath22)" + stroke="none" + id="text407" + style="white-space: pre;">SessionFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="rgb(232,232,232)" + id="g413"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect411"/> + fill="url(#linearGradient8)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="url(#linearGradient8)" + id="g417"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect415"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-599,-10.5)" + id="g425"> + x="3" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image419" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image421" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Session + x="47" + y="19" + clip-path="url(#clipPath22)" + stroke="none" + id="text423" + style="white-space: pre;">SessionFactory + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-380,-16.5)" + stroke="gray" + id="g431"> + x="2" + width="188" + height="1" + y="36" + clip-path="url(#clipPath24)" + stroke="none" + id="rect427"/> + x="189" + width="1" + height="35" + y="2" + clip-path="url(#clipPath24)" + stroke="none" + id="rect429"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-379,-15.5)" + stroke="rgb(232,232,232)" + id="g435"> + x="0" + width="188" + height="35" + y="0" + clip-path="url(#clipPath25)" + stroke="none" + id="rect433"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-379,-15.5)" + stroke="silver" + id="g439"> + d="M0 0 L188 0 L188 35 L0 35 L0 0 ZM1 1 L187 1 L187 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath25)" + stroke="none" + id="path437"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="rgb(232,232,232)" + id="g443"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect441"/> + fill="url(#linearGradient9)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="url(#linearGradient9)" + id="g447"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect445"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-374,-10.5)" + id="g457"> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image449" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image451" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + EntityManagerFactory + x="47" + y="19" + clip-path="url(#clipPath27)" + stroke="none" + id="text455" + style="white-space: pre;">SessionFactoryImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="rgb(232,232,232)" + id="g461"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect459"/> + fill="url(#linearGradient10)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="url(#linearGradient10)" + id="g465"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect463"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-374,-10.5)" + id="g475"> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image467" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image469" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + EntityManagerFactory + x="47" + y="19" + clip-path="url(#clipPath27)" + stroke="none" + id="text473" + style="white-space: pre;">SessionFactoryImpl + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-613,343.5)" + stroke="gray" + id="g531"> + x="2" + width="174" + height="1" + y="36" + clip-path="url(#clipPath34)" + stroke="none" + id="rect527"/> + x="175" + width="1" + height="35" + y="2" + clip-path="url(#clipPath34)" + stroke="none" + id="rect529"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-612,344.5)" + stroke="rgb(232,232,232)" + id="g535"> + x="0" + width="174" + height="35" + y="0" + clip-path="url(#clipPath35)" + stroke="none" + id="rect533"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-612,344.5)" + stroke="silver" + id="g539"> + d="M0 0 L174 0 L174 35 L0 35 L0 0 ZM1 1 L173 1 L173 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath35)" + stroke="none" + id="path537"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="rgb(232,232,232)" + id="g543"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect541"/> + fill="url(#linearGradient13)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="url(#linearGradient13)" + id="g547"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect545"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-607,349.5)" + id="g555"> + x="3" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image549" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image551" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactory + x="47" + y="19" + clip-path="url(#clipPath37)" + stroke="none" + id="text553" + style="white-space: pre;">EntityTransaction + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="rgb(232,232,232)" + id="g559"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect557"/> + fill="url(#linearGradient14)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="url(#linearGradient14)" + id="g563"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect561"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-607,349.5)" + id="g571"> + x="3" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image565" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image567" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactory + x="47" + y="19" + clip-path="url(#clipPath37)" + stroke="none" + id="text569" + style="white-space: pre;">EntityTransaction + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-594.5,223.5)" + stroke="gray" + id="g577"> + x="2" + width="137" + height="1" + y="36" + clip-path="url(#clipPath39)" + stroke="none" + id="rect573"/> + x="138" + width="1" + height="35" + y="2" + clip-path="url(#clipPath39)" + stroke="none" + id="rect575"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-593.5,224.5)" + stroke="rgb(232,232,232)" + id="g581"> + x="0" + width="137" + height="35" + y="0" + clip-path="url(#clipPath40)" + stroke="none" + id="rect579"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-593.5,224.5)" + stroke="silver" + id="g585"> + d="M0 0 L137 0 L137 35 L0 35 L0 0 ZM1 1 L136 1 L136 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath40)" + stroke="none" + id="path583"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="rgb(232,232,232)" + id="g589"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect587"/> + fill="url(#linearGradient15)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="url(#linearGradient15)" + id="g593"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect591"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-588.5,229.5)" + id="g601"> + x="3" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image595" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image597" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactoryImpl + x="47" + y="19" + clip-path="url(#clipPath42)" + stroke="none" + id="text599" + style="white-space: pre;">Transaction + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="rgb(232,232,232)" + id="g605"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect603"/> + fill="url(#linearGradient16)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="url(#linearGradient16)" + id="g609"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect607"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-588.5,229.5)" + id="g617"> + x="3" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image611" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image613" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactoryImpl + x="47" + y="19" + clip-path="url(#clipPath42)" + stroke="none" + id="text615" + style="white-space: pre;">Transaction + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-369.5,223.5)" + stroke="gray" + id="g623"> + x="2" + width="167" + height="1" + y="36" + clip-path="url(#clipPath44)" + stroke="none" + id="rect619"/> + x="168" + width="1" + height="35" + y="2" + clip-path="url(#clipPath44)" + stroke="none" + id="rect621"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-368.5,224.5)" + stroke="rgb(232,232,232)" + id="g627"> + x="0" + width="167" + height="35" + y="0" + clip-path="url(#clipPath45)" + stroke="none" + id="rect625"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-368.5,224.5)" + stroke="silver" + id="g631"> + d="M0 0 L167 0 L167 35 L0 35 L0 0 ZM1 1 L166 1 L166 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath45)" + stroke="none" + id="path629"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="rgb(232,232,232)" + id="g635"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect633"/> + fill="url(#linearGradient17)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="url(#linearGradient17)" + id="g639"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect637"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-363.5,229.5)" + id="g647"> + x="3" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image641" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image643" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionImpl + x="47" + y="19" + clip-path="url(#clipPath47)" + stroke="none" + id="text645" + style="white-space: pre;">TransactionImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="rgb(232,232,232)" + id="g651"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect649"/> + fill="url(#linearGradient18)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="url(#linearGradient18)" + id="g655"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect653"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-363.5,229.5)" + id="g663"> + x="3" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image657" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image659" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionImpl + x="47" + y="19" + clip-path="url(#clipPath47)" + stroke="none" + id="text661" + style="white-space: pre;">TransactionImpl + - - - - - - - + fill="rgb(0,130,0)" + stroke-miterlimit="1.45" + transform="matrix(1,0,0,1,649,37)" + stroke="rgb(0,130,0)" + id="g695"> + fill="none" + d="M-525 20.5405 L-525 92.4595" + clip-path="url(#clipPath2)" + id="path679"/> + + + + + + + + + + + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 482.048981, 144.549438)" + stroke="gray" + id="g-1"> - - + x="2" + width="205" + height="1" + y="36" + clip-path="url(#clip-1)" + stroke="none" + id="rect-1"/> + x="206" + width="1" + height="35" + y="2" + clip-path="url(#clip-1)" + stroke="none" + id="rect-2"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 483.048981, 145.549438)" + stroke="rgb(232,232,232)" + id="g-2"> + + + + + + + + + + + + + x="3" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-1" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-2" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityTransaction + x="47" + y="19" + clip-path="url(#clip-4)" + stroke="none" + id="text-1" + style="white-space: pre;">EntityManagerFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 484.048981, 146.549438)" + stroke="rgb(232,232,232)" + id="g-7"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clip-3)" + stroke="none" + id="rect-6"/> + fill="url(#gradient-2)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 484.048981, 146.549438)" + stroke="url(#gradient-2)" + id="g-8"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clip-3)" + stroke="none" + id="rect-7"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(504.04898,150.54944)" + id="g-9"> + x="3" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-3" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-4" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityTransaction + x="47" + y="19" + clip-path="url(#clip-4)" + stroke="none" + id="text-2" + style="white-space:pre">EntityManager + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 505.548981, 24.549469)" + stroke="gray" + id="g-10"> + x="2" + width="158" + height="1" + y="36" + clip-path="url(#clip-5)" + stroke="none" + id="rect-8"/> + x="159" + width="1" + height="35" + y="2" + clip-path="url(#clip-5)" + stroke="none" + id="rect-9"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 506.548981, 25.549469)" + stroke="rgb(232,232,232)" + id="g-11"> + x="0" + width="158" + height="35" + y="0" + clip-path="url(#clip-6)" + stroke="none" + id="rect-10"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 506.548981, 25.549469)" + stroke="silver" + id="g-12"> + d="M0 0 L158 0 L158 35 L0 35 L0 0 ZM1 1 L157 1 L157 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clip-6)" + stroke="none" + id="path-14"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="rgb(232,232,232)" + id="g-13"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-11"/> + fill="url(#gradient-3)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="url(#gradient-3)" + id="g-14"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-12"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1, 0, 0, 1, 511.548981, 30.549469)" + id="g-15"> + x="3" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-5" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-6" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Transaction + x="47" + y="19" + clip-path="url(#clip-8)" + stroke="none" + id="text-3" + style="white-space: pre;">SessionFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="rgb(232,232,232)" + id="g-16"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-13"/> + fill="url(#gradient-4)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="url(#gradient-4)" + id="g-17"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-14"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(531.54898,30.549469)" + id="g-18"> + x="3" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-7" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-8" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Transaction + x="47" + y="19" + clip-path="url(#clip-8)" + stroke="none" + id="text-4" + style="white-space:pre">Session + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 730.54895, 24.549469)" + stroke="gray" + id="g-19"> + x="2" + width="188" + height="1" + y="36" + clip-path="url(#clip-9)" + stroke="none" + id="rect-15"/> + x="189" + width="1" + height="35" + y="2" + clip-path="url(#clip-9)" + stroke="none" + id="rect-16"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 731.54895, 25.549469)" + stroke="rgb(232,232,232)" + id="g-20"> + x="0" + width="188" + height="35" + y="0" + clip-path="url(#clip-10)" + stroke="none" + id="rect-17"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 731.54895, 25.549469)" + stroke="silver" + id="g-21"> + d="M0 0 L188 0 L188 35 L0 35 L0 0 ZM1 1 L187 1 L187 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clip-10)" + stroke="none" + id="path-15"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="rgb(232,232,232)" + id="g-22"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-18"/> + fill="url(#gradient-5)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="url(#gradient-5)" + id="g-23"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-19"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1, 0, 0, 1, 736.54895, 30.549469)" + id="g-24"> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-9" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-10" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + TransactionImpl + x="47" + y="19" + clip-path="url(#clip-12)" + stroke="none" + id="text-5" + style="white-space: pre;">SessionFactoryImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="rgb(232,232,232)" + id="g-25"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-20"/> + fill="url(#gradient-6)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="url(#gradient-6)" + id="g-26"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-21"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(745.54895,30.549469)" + id="g-27"> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-12" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-13" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + TransactionImpl - - - - - - - - - - - - - - - - - - + x="47" + y="19" + clip-path="url(#clip-12)" + stroke="none" + id="text-6" + style="white-space:pre">SessionImpl + From b30a68f5be8aeef7e8b1f8110fabfe08b4caf0b3 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Thu, 13 May 2021 09:49:14 +0200 Subject: [PATCH 29/45] HHH-14596 WhereAnnotatedOneToManySizeTest fails on HANA database --- .../test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java index a5adb3af5b..a3ec5d5a35 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java @@ -10,6 +10,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.List; +import org.hibernate.dialect.AbstractHANADialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.query.spi.QueryImplementor; @@ -89,6 +90,7 @@ public class WhereAnnotatedOneToManySizeTest extends BaseCoreFunctionalTestCase @Test @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + @SkipForDialect(value = AbstractHANADialect.class, comment = "HANA db does not support correlated subqueries in the ORDER BY clause") public void orderBy_sizeOf() { inSession( session -> { QueryImplementor query = session.createQuery( @@ -101,6 +103,7 @@ public class WhereAnnotatedOneToManySizeTest extends BaseCoreFunctionalTestCase @Test @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + @SkipForDialect(value = AbstractHANADialect.class, comment = "HANA db does not support correlated subqueries in the ORDER BY clause") public void orderBy_dotSize() { inSession( session -> { QueryImplementor query = session.createQuery( From 8b9b5e7e68893dc9c84120c8295d7afad8371290 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Sun, 16 May 2021 14:55:57 +0100 Subject: [PATCH 30/45] HHH-14610 Upgrade to Byte Buddy 1.10.22 --- gradle/libraries.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index cf98d0a77b..9fc6ca1d61 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -25,7 +25,7 @@ ext { jakartaWeldVersion = '4.0.1.SP1' javassistVersion = '3.27.0-GA' - byteBuddyVersion = '1.10.21' + byteBuddyVersion = '1.10.22' agroalVersion = '1.9' From eb6c68cdc608ba90cd9deeb654a4e3dccde03ccc Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Tue, 18 May 2021 22:05:17 +0100 Subject: [PATCH 31/45] HHH-14621 Introduce new methods on EventListenerGroup which allow Hibernate Reactive to fire events more efficiently --- .../internal/EventListenerGroupImpl.java | 54 +++++++++++++++++++ .../event/service/spi/EventListenerGroup.java | 52 ++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java index 8bdcf3710f..fb6255eb84 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java @@ -11,8 +11,12 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.function.BiConsumer; +import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import org.hibernate.event.service.spi.DuplicationStrategy; @@ -33,8 +37,10 @@ import org.jboss.logging.Logger; * @author Sanne Grinovero */ class EventListenerGroupImpl implements EventListenerGroup { + private static final Logger log = Logger.getLogger( EventListenerGroupImpl.class ); private static final Set DEFAULT_DUPLICATION_STRATEGIES = Collections.unmodifiableSet( makeDefaultDuplicationStrategy() ); + private static final CompletableFuture COMPLETED = CompletableFuture.completedFuture( null ); private final EventType eventType; private final CallbackRegistry callbackRegistry; @@ -114,6 +120,54 @@ class EventListenerGroupImpl implements EventListenerGroup { } } + @Override + public CompletionStage fireEventOnEachListener( + final U event, + final Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event ) ); + } + } + return ret; + } + + @Override + public CompletionStage fireEventOnEachListener( + U event, X param, Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event, param ) ); + } + } + return ret; + } + + @Override + public CompletionStage fireLazyEventOnEachListener( + final Supplier eventSupplier, + final Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + final U event = eventSupplier.get(); + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event ) ); + } + } + return ret; + } + @Override public void addDuplicationStrategy(DuplicationStrategy strategy) { if ( duplicationStrategies == DEFAULT_DUPLICATION_STRATEGIES ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java b/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java index df62868c48..84872efe28 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java @@ -8,7 +8,10 @@ package org.hibernate.event.service.spi; import java.io.Serializable; import java.util.Map; +import java.util.concurrent.CompletionStage; import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Supplier; import org.hibernate.Incubating; @@ -113,4 +116,53 @@ public interface EventListenerGroup extends Serializable { @Incubating void fireEventOnEachListener(final U event, X param, final EventActionWithParameter actionOnEvent); + /** + * Similar to {@link #fireEventOnEachListener(Object, Function)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

Used by Hibernate Reactive

+ * @param event The event being fired + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + CompletionStage fireEventOnEachListener(final U event, final Function>> fun); + + /** + * Similar to {@link #fireEventOnEachListener(Object, Object, Function)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

Used by Hibernate Reactive

+ * @param event The event being fired + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @param an additional parameter to be passed to the function fun + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + public CompletionStage fireEventOnEachListener(U event, X param, Function>> fun); + + /** + * Similar to {@link #fireLazyEventOnEachListener(Supplier, BiConsumer)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

This variant expects a Supplier of the event, rather than the event directly; this is useful for the + * event types which are commonly configured with no listeners at all, so to allow skipping creating the + * event; use only for event types which are known to be expensive while the listeners are commonly empty.

+ *

Used by Hibernate Reactive

+ * @param eventSupplier A supplier able to produce the actual event + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + CompletionStage fireLazyEventOnEachListener(final Supplier eventSupplier, final Function>> fun); + } From b9270e44b186dd0f2eb9821e1c766e01249d4bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 19 May 2021 16:25:35 +0200 Subject: [PATCH 32/45] HHH-14620 Do not initialize collections just to take a snapshot of their size As far as I can tell this is safe enough for dirty tracking: * The collection tracker will return a size of -1 for that collection * Which is exactly the behavior we currently get after $$_hibernane_clearDirtyCollectionNames is called if a collection has been "retrieved" (getter called) but was not initialized. * This will mainly prevent some optimizations because we will no longer be able to tell whether a collection is "dirty" or not. I think we should be able to restore those optimizations: for PersistentCollection instances, we would store the "initial" size inside the collection itself upon initialization, and we would compare THAT size to the current size in implementations of $$_hibernate_areCollectionFieldsDirty (see org.hibernate.bytecode.enhance.internal.bytebuddy.CodeTemplates). Alternatively we could store the CollectionTracker inside the PersistentCollection so that the collection can update the tracker upon initialization. However, that's outside the scope of this bug, that would require significant testing, and that may cause conflicts with ORM 6, so I won't do it here. --- .../LazyAttributeLoadingInterceptor.java | 8 ++++++ .../ondemandload/OnDemandLoadTest.java | 26 ++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java index 7880edbb57..1b084cccd2 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java @@ -16,6 +16,7 @@ import java.util.Set; import org.hibernate.LockMode; import org.hibernate.bytecode.enhance.spi.CollectionTracker; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; +import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.SelfDirtinessTracker; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; @@ -152,11 +153,18 @@ public class LazyAttributeLoadingInterceptor extends AbstractLazyLoadInterceptor private void takeCollectionSizeSnapshot(Object target, String fieldName, Object value) { if ( value instanceof Collection && target instanceof SelfDirtinessTracker ) { + // This must be called first, so that we remember that there is a collection out there, + // even if we don't know its size (see below). CollectionTracker tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker(); if ( tracker == null ) { ( (SelfDirtinessTracker) target ).$$_hibernate_clearDirtyAttributes(); tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker(); } + + if ( value instanceof PersistentCollection && !( (PersistentCollection) value ).wasInitialized() ) { + // Cannot take a snapshot of an un-initialized collection. + return; + } tracker.add( fieldName, ( (Collection) value ).size() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java index e242c1c3a0..68642adeb0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java @@ -119,16 +119,17 @@ public class OnDemandLoadTest extends BaseCoreFunctionalTestCase { store.getInventories().size(); assertTrue( isPropertyInitialized( store, "inventories" ) ); - // the extra Session is the temp Session needed to perform the init - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + // the extra Sessions are the temp Sessions needed to perform the init: + // first the entity, then the collection (since it's lazy) + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); // clear Session again. The collection should still be recognized as initialized from above s.clear(); assertNotNull( store ); assertTrue( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); // lets clear the Session again and this time reload the Store s.clear(); @@ -138,21 +139,22 @@ public class OnDemandLoadTest extends BaseCoreFunctionalTestCase { // collection should be back to uninitialized since we have a new entity instance assertFalse( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); store.getInventories().size(); assertTrue( isPropertyInitialized( store, "inventories" ) ); - // the extra Session is the temp Session needed to perform the init - assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); + // the extra Sessions are the temp Sessions needed to perform the init: + // first the entity, then the collection (since it's lazy) + assertEquals( 5, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 4, sessionFactory().getStatistics().getSessionCloseCount() ); // clear Session again. The collection should still be recognized as initialized from above s.clear(); assertNotNull( store ); assertTrue( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 5, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 4, sessionFactory().getStatistics().getSessionCloseCount() ); } ); } From 12cb577f9f7febf0cfcd709289495aa7be8c799a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 19 May 2021 16:10:03 +0200 Subject: [PATCH 33/45] HHH-14620 Test incorrect initialization of a collection with extended bytecode enhancement --- .../lazy/LazyCollectionLoadingTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java index f61895cd5d..ab4bd31366 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java @@ -36,6 +36,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.Hibernate.isInitialized; import static org.hibernate.Hibernate.isPropertyInitialized; import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; @@ -101,7 +102,40 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { checkDirtyTracking( parent ); assertThat( children1, sameInstance( children2 ) ); + + assertFalse( isInitialized( children1 ) ); assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); + } ); + } + + @Test + @TestForIssue( jiraKey = "HHH-14620" ) + public void testTransaction_noProxy() { + doInHibernate( this::sessionFactory, s -> { + // find will not return a proxy, which is exactly what we want here. + Parent parent = s.find( Parent.class, parentID ); + assertThat( parent, notNullValue() ); + assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); + assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); + assertFalse( isPropertyInitialized( parent, "children" ) ); + checkDirtyTracking( parent ); + + List children1 = parent.children; + List children2 = parent.children; + + assertTrue( isPropertyInitialized( parent, "children" ) ); + checkDirtyTracking( parent ); + + assertThat( children1, sameInstance( children2 ) ); + + // This check is important: a bug used to cause the collection to be initialized + // during the call to parent.children above. + // Note the same problem would occur if we were using getters: + // we only need extended enhancement to be enabled. + assertFalse( isInitialized( children1 ) ); + assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); } ); } @@ -122,7 +156,10 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { checkDirtyTracking( parent ); assertThat( children1, sameInstance( children2 ) ); + + assertFalse( isInitialized( children1 ) ); assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); } // --- // From ccc5eb13054af130f9132fcf1c7808901fa9e2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 20 May 2021 08:46:36 +0200 Subject: [PATCH 34/45] HHH-14620 Remove duplicate assertions in LazyCollectionLoadingTest --- .../bytecode/enhancement/lazy/LazyCollectionLoadingTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java index ab4bd31366..1433a80e20 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java @@ -91,7 +91,6 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { Parent parent = s.load( Parent.class, parentID ); assertThat( parent, notNullValue() ); assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); - assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); assertFalse( isPropertyInitialized( parent, "children" ) ); checkDirtyTracking( parent ); @@ -117,7 +116,6 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { Parent parent = s.find( Parent.class, parentID ); assertThat( parent, notNullValue() ); assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); - assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); assertFalse( isPropertyInitialized( parent, "children" ) ); checkDirtyTracking( parent ); @@ -145,7 +143,6 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { parent = s.load( Parent.class, parentID ); assertThat( parent, notNullValue() ); assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); - assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); assertFalse( isPropertyInitialized( parent, "children" ) ); } ); From e6688f8ebc83b5562225a1969d2967f28ddf5a0d Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Wed, 19 May 2021 21:00:28 +0100 Subject: [PATCH 35/45] HHH-14622 Improved iteration of PreLoadEventListener --- .../engine/internal/TwoPhaseLoad.java | 43 +++---------------- .../java/org/hibernate/loader/Loader.java | 8 +--- .../process/internal/AbstractRowReader.java | 8 +--- 3 files changed, 9 insertions(+), 50 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java index 8dfc849ed5..20b94278bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java @@ -105,29 +105,6 @@ public final class TwoPhaseLoad { } } - /** - * @deprecated This method will be removed. Use {@link #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable)} instead. - * - * @param entity The entity being loaded - * @param readOnly Is the entity being loaded as read-only - * @param session The Session - * @param preLoadEvent The (re-used) pre-load event - */ - @Deprecated - public static void initializeEntity( - final Object entity, - final boolean readOnly, - final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent) { - final EventListenerGroup listenerGroup = session - .getFactory() - .getServiceRegistry() - .getService( EventListenerRegistry.class ) - .getEventListenerGroup( EventType.PRE_LOAD ); - final Iterable listeners = listenerGroup.listeners(); - initializeEntity( entity, readOnly, session, preLoadEvent, listeners, EntityResolver.DEFAULT ); - } - /** * Perform the second step of 2-phase load. Fully initialize the entity * instance. @@ -140,15 +117,13 @@ public final class TwoPhaseLoad { * @param readOnly Is the entity being loaded as read-only * @param session The Session * @param preLoadEvent The (re-used) pre-load event - * @param preLoadEventListeners the pre-load event listeners */ public static void initializeEntity( final Object entity, final boolean readOnly, final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners) { - initializeEntity( entity, readOnly, session, preLoadEvent, preLoadEventListeners, EntityResolver.DEFAULT ); + final PreLoadEvent preLoadEvent) { + initializeEntity( entity, readOnly, session, preLoadEvent, EntityResolver.DEFAULT ); } /** @@ -163,7 +138,6 @@ public final class TwoPhaseLoad { * @param readOnly Is the entity being loaded as read-only * @param session The Session * @param preLoadEvent The (re-used) pre-load event - * @param preLoadEventListeners the pre-load event listeners * @param entityResolver the resolver used for to-one entity associations * (not used when an entity is a bytecode-enhanced lazy entity) */ @@ -172,7 +146,6 @@ public final class TwoPhaseLoad { final boolean readOnly, final SharedSessionContractImplementor session, final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners, final EntityResolver entityResolver) { final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityEntry entityEntry = persistenceContext.getEntry( entity ); @@ -180,7 +153,7 @@ public final class TwoPhaseLoad { throw new AssertionFailure( "possible non-threadsafe access to the session" ); } initializeEntityEntryLoadedState( entity, entityEntry, session, entityResolver ); - initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent, preLoadEventListeners ); + initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent ); } public static void initializeEntityEntryLoadedState( @@ -261,8 +234,7 @@ public final class TwoPhaseLoad { final EntityEntry entityEntry, final boolean readOnly, final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners) throws HibernateException { + final PreLoadEvent preLoadEvent) throws HibernateException { final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityPersister persister = entityEntry.getPersister(); @@ -274,9 +246,8 @@ public final class TwoPhaseLoad { //Must occur after resolving identifiers! if ( session.isEventSource() ) { preLoadEvent.setEntity( entity ).setState( hydratedState ).setId( id ).setPersister( persister ); - for ( PreLoadEventListener listener : preLoadEventListeners ) { - listener.onPreLoad( preLoadEvent ); - } + session.getFactory().getFastSessionServices() + .eventListenerGroup_PRE_LOAD.fireEventOnEachListener( preLoadEvent, PreLoadEventListener::onPreLoad ); } persister.setPropertyValues( entity, hydratedState ); @@ -589,7 +560,7 @@ public final class TwoPhaseLoad { /** * Implementations determine how a to-one associations is resolved. * - * @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable, EntityResolver) + * @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, EntityResolver) */ public interface EntityResolver { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java index 2095ecc0f6..db8e0e2fbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/Loader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/Loader.java @@ -1184,14 +1184,8 @@ public abstract class Loader { LOG.tracev( "Total objects hydrated: {0}", hydratedObjectsSize ); if ( hydratedObjectsSize != 0 ) { - final Iterable listeners = session - .getFactory() - .getFastSessionServices() - .eventListenerGroup_PRE_LOAD - .listeners(); - for ( Object hydratedObject : hydratedObjects ) { - TwoPhaseLoad.initializeEntity( hydratedObject, readOnly, session, pre, listeners ); + TwoPhaseLoad.initializeEntity( hydratedObject, readOnly, session, pre ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java index 4e640e41e1..32f8b01870 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java @@ -237,19 +237,13 @@ public abstract class AbstractRowReader implements RowReader { } final SharedSessionContractImplementor session = context.getSession(); - final Iterable listeners = session - .getFactory() - .getFastSessionServices() - .eventListenerGroup_PRE_LOAD - .listeners(); for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) { TwoPhaseLoad.initializeEntity( registration.getInstance(), context.isReadOnly(), session, - preLoadEvent, - listeners + preLoadEvent ); } } From 6dc3b4a7263ffce501544499fe4c443b3f871228 Mon Sep 17 00:00:00 2001 From: gavin Date: Wed, 19 May 2021 11:17:02 +0200 Subject: [PATCH 36/45] make logFlushResults() protected for the benefit of HR --- .../event/internal/AbstractFlushingEventListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java index d596c6e8e6..b70a616665 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java @@ -104,8 +104,8 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi logFlushResults( event ); } - @SuppressWarnings( value = {"unchecked"} ) - private void logFlushResults(FlushEvent event) { + @SuppressWarnings("unchecked") + protected void logFlushResults(FlushEvent event) { if ( !LOG.isDebugEnabled() ) { return; } From bf19f98c2d59fb60cf4043cab322dfd68a9e5101 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 19 May 2021 15:50:24 +0200 Subject: [PATCH 37/45] HHH-14619 Test and fix ClassCastException because collection of uninitialized proxy is dirty checked --- .../AbstractFlushingEventListener.java | 1 - .../DefaultFlushEntityEventListener.java | 1 + .../DirtyCollectionSearchVisitor.java | 17 +- .../lazy/LazyProxyWithCollectionTest.java | 166 ++++++++++++++++++ 4 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java index b70a616665..98502d8c68 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java @@ -219,7 +219,6 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi final int count = entityEntries.length; for ( Map.Entry me : entityEntries ) { - // Update the status of the object and if necessary, schedule an update EntityEntry entry = me.getValue(); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java index 23e4955d5f..ef9815b00c 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java @@ -485,6 +485,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener private boolean hasDirtyCollections(FlushEntityEvent event, EntityPersister persister, Status status) { if ( isCollectionDirtyCheckNecessary( persister, status ) ) { DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor( + event.getEntity(), event.getSession(), persister.getPropertyVersionability() ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java index 73fb564b6e..3cfcd16417 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java @@ -7,7 +7,9 @@ package org.hibernate.event.internal; import org.hibernate.HibernateException; +import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.EventSource; import org.hibernate.type.CollectionType; @@ -22,11 +24,19 @@ import org.hibernate.type.CollectionType; */ public class DirtyCollectionSearchVisitor extends AbstractVisitor { + private final EnhancementAsProxyLazinessInterceptor interceptor; + private final boolean[] propertyVersionability; private boolean dirty; - private boolean[] propertyVersionability; - public DirtyCollectionSearchVisitor(EventSource session, boolean[] propertyVersionability) { + public DirtyCollectionSearchVisitor(Object entity, EventSource session, boolean[] propertyVersionability) { super( session ); + EnhancementAsProxyLazinessInterceptor interceptor = null; + if ( entity instanceof PersistentAttributeInterceptable ) { + if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) { + interceptor = (EnhancementAsProxyLazinessInterceptor) ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); + } + } + this.interceptor = interceptor; this.propertyVersionability = propertyVersionability; } @@ -45,6 +55,9 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor { // return (ah==null) ? true : searchForDirtyCollections(ah, type); } else { + if ( interceptor != null && !interceptor.isAttributeLoaded( type.getName() ) ) { + return null; + } // if not wrapped yet, its dirty (this can't occur, because // we now always call wrap() before getting to here) // return ( ! (obj instanceof PersistentCollection) ) ? diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java new file mode 100644 index 0000000000..d818fa52e8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java @@ -0,0 +1,166 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.bytecode.enhancement.lazy; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.HibernateException; +import org.hibernate.bytecode.enhance.spi.UnloadedClass; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.LoadEvent; +import org.hibernate.event.spi.LoadEventListener; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Version; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Christian Beikov + */ +@TestForIssue( jiraKey = "HHH-14619" ) +@RunWith( BytecodeEnhancerRunner.class ) +public class LazyProxyWithCollectionTest extends BaseCoreFunctionalTestCase { + + private Long childId; + + @Override + public Class[] getAnnotatedClasses() { + return new Class[]{Parent.class, Child.class}; + } + + @Before + public void prepare() { + doInJPA( this::sessionFactory, em -> { + Child c = new Child(); + em.persist( c ); + childId = c.getId(); + } ); + } + + @Test + public void testReference() { + doInJPA( this::sessionFactory, em -> { + Child child = em.getReference( Child.class, childId ); + Parent parent = new Parent(); + parent.child = child; + em.persist( parent ); + // Class cast exception occurs during auto-flush + em.find( Parent.class, parent.getId() ); + } ); + } + + @Test + public void testLazyCollection() { + doInJPA( this::sessionFactory, em -> { + Child child = em.find( Child.class, childId ); + Parent parent = new Parent(); + parent.child = child; + em.persist( parent ); + child.children = new HashSet<>(); + // Class cast exception occurs during auto-flush + em.find( Parent.class, parent.getId() ); + } ); + } + + // --- // + + @Entity + @Table( name = "PARENT" ) + private static class Parent { + + @Id + @GeneratedValue( strategy = GenerationType.AUTO ) + Long id; + + @OneToOne( fetch = FetchType.LAZY ) + Child child; + + public Long getId() { + return id; + } + + public Child getChild() { + return child; + } + + public void setChild(Child child) { + this.child = child; + } + } + + @Entity + @Table( name = "CHILD" ) + private static class Child { + + @Id + @GeneratedValue( strategy = GenerationType.AUTO ) + Long id; + @Version + Long version; + + String name; + + @OneToMany + Set children = new HashSet<>(); + + Child() { + // No-arg constructor necessary for proxy factory + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + } + +} From a57c0e34ff99dc77d4b372e225fdd65d1373b82a Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Thu, 20 May 2021 14:27:01 +0200 Subject: [PATCH 38/45] HHH-14618 Allow passing multiple script source files separated by comma --- .../tool/schema/internal/Helper.java | 47 ++++++---- .../exec/ScriptSourceInputAggregate.java | 87 +++++++++++++++++++ .../schemagen/JpaFileSchemaGeneratorTest.java | 4 - .../schemagen/JpaSchemaGeneratorTest.java | 36 ++++++-- ...maGeneratorWithHbm2DdlCharsetNameTest.java | 4 - .../test/schemagen/create-script-source2.sql | 1 + .../test/schemagen/drop-script-source2.sql | 1 + .../iso8859/create-script-source2.sql | 1 + .../schemagen/iso8859/drop-script-source2.sql | 1 + .../schemagen/iso8859/load-script-source2.sql | 1 + .../test/schemagen/load-script-source2.sql | 1 + 11 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/create-script-source2.sql create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/drop-script-source2.sql create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql create mode 100644 hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/load-script-source2.sql diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java index 1701ed4e48..49c66cff17 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java @@ -12,6 +12,7 @@ import java.io.Writer; import java.net.URL; import java.sql.SQLException; import java.util.Map; +import java.util.regex.Pattern; import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; @@ -24,6 +25,7 @@ import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.schema.extract.spi.DatabaseInformation; import org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl; +import org.hibernate.tool.schema.internal.exec.ScriptSourceInputAggregate; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromFile; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromReader; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromUrl; @@ -33,8 +35,6 @@ import org.hibernate.tool.schema.internal.exec.ScriptTargetOutputToWriter; import org.hibernate.tool.schema.spi.ScriptSourceInput; import org.hibernate.tool.schema.spi.ScriptTargetOutput; -import org.jboss.logging.Logger; - /** * Helper methods. * @@ -43,6 +43,7 @@ import org.jboss.logging.Logger; public class Helper { private static final CoreMessageLogger log = CoreLogging.messageLogger( Helper.class ); + private static final Pattern COMMA_PATTERN = Pattern.compile( "\\s*,\\s*" ); public static ScriptSourceInput interpretScriptSourceSetting( Object scriptSourceSetting, @@ -55,24 +56,40 @@ public class Helper { final String scriptSourceSettingString = scriptSourceSetting.toString(); log.debugf( "Attempting to resolve script source setting : %s", scriptSourceSettingString ); - // setting could be either: - // 1) string URL representation (i.e., "file://...") - // 2) relative file path (resource lookup) - // 3) absolute file path - - log.trace( "Trying as URL..." ); - // ClassLoaderService.locateResource() first tries the given resource name as url form... - final URL url = classLoaderService.locateResource( scriptSourceSettingString ); - if ( url != null ) { - return new ScriptSourceInputFromUrl( url, charsetName ); + final String[] paths = COMMA_PATTERN.split( scriptSourceSettingString ); + if ( paths.length == 1 ) { + return interpretScriptSourceSetting( scriptSourceSettingString, classLoaderService, charsetName ); + } + final ScriptSourceInput[] inputs = new ScriptSourceInput[paths.length]; + for ( int i = 0; i < paths.length; i++ ) { + inputs[i] = interpretScriptSourceSetting( paths[i], classLoaderService, charsetName ) ; } - // assume it is a File path - final File file = new File( scriptSourceSettingString ); - return new ScriptSourceInputFromFile( file, charsetName ); + return new ScriptSourceInputAggregate( inputs ); } } + private static ScriptSourceInput interpretScriptSourceSetting( + String scriptSourceSettingString, + ClassLoaderService classLoaderService, + String charsetName) { + // setting could be either: + // 1) string URL representation (i.e., "file://...") + // 2) relative file path (resource lookup) + // 3) absolute file path + + log.trace( "Trying as URL..." ); + // ClassLoaderService.locateResource() first tries the given resource name as url form... + final URL url = classLoaderService.locateResource( scriptSourceSettingString ); + if ( url != null ) { + return new ScriptSourceInputFromUrl( url, charsetName ); + } + + // assume it is a File path + final File file = new File( scriptSourceSettingString ); + return new ScriptSourceInputFromFile( file, charsetName ); + } + public static ScriptTargetOutput interpretScriptTargetSetting( Object scriptTargetSetting, ClassLoaderService classLoaderService, diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java new file mode 100644 index 0000000000..6981f60f90 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java @@ -0,0 +1,87 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.internal.exec; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractor; +import org.hibernate.tool.schema.spi.ScriptSourceInput; + +/** + * A script source input that aggregates over multiple other {@link ScriptSourceInput}. + * + * @author Christian Beikov + */ +public class ScriptSourceInputAggregate implements ScriptSourceInput { + + private final ScriptSourceInput[] inputs; + + /** + * Constructs a ScriptSourceInputAggregate + * + * @param inputs The script source inputs + */ + public ScriptSourceInputAggregate(ScriptSourceInput[] inputs) { + this.inputs = inputs; + } + + @Override + public void prepare() { + for ( ScriptSourceInput input : inputs ) { + input.prepare(); + } + } + + @Override + public void release() { + Throwable t = null; + for ( ScriptSourceInput input : inputs ) { + try { + input.release(); + } + catch (Throwable t2) { + if ( t == null ) { + t = t2; + } + else { + t.addSuppressed( t2 ); + } + } + } + if ( t != null ) { + doThrow( t ); + } + } + + @SuppressWarnings("unchecked") + private static void doThrow(Throwable e) throws T { + throw (T) e; + } + + @Override + public List read(ImportSqlCommandExtractor commandExtractor) { + final List[] lists = new List[inputs.length]; + int size = 0; + for ( int i = 0; i < inputs.length; i++ ) { + lists[i] = inputs[i].read( commandExtractor ); + size += lists[i].size(); + } + + final List list = new ArrayList<>( size ); + for ( List strings : lists ) { + list.addAll( strings ); + } + return list; + } + + @Override + public String toString() { + return "ScriptSourceInputAggregate(" + Arrays.toString( inputs ) + ")"; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaFileSchemaGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaFileSchemaGeneratorTest.java index 324b399b7a..8f14520323 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaFileSchemaGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaFileSchemaGeneratorTest.java @@ -30,10 +30,6 @@ public class JpaFileSchemaGeneratorTest extends JpaSchemaGeneratorTest { return toFilePath(super.getDropSqlScript()); } - protected String toFilePath(String relativePath) { - return Thread.currentThread().getContextClassLoader().getResource( relativePath ).getFile(); - } - @Override protected String getResourceUrlString(String resource) { return resource; diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java index 8ebb3cbb80..51aa159899 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/JpaSchemaGeneratorTest.java @@ -8,6 +8,7 @@ package org.hibernate.jpa.test.schemagen; import java.net.URL; import java.util.Map; +import java.util.function.Function; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @@ -20,6 +21,7 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; +import org.hibernate.test.legacy.S; import org.junit.Assert; import org.junit.Test; @@ -29,9 +31,9 @@ import org.junit.Test; @RequiresDialect( H2Dialect.class ) public class JpaSchemaGeneratorTest extends BaseEntityManagerFunctionalTestCase { - private final String LOAD_SQL = getScriptFolderPath() + "load-script-source.sql"; - private final String CREATE_SQL = getScriptFolderPath() + "create-script-source.sql"; - private final String DROP_SQL = getScriptFolderPath() + "drop-script-source.sql"; + private final String LOAD_SQL = getScriptFolderPath() + "load-script-source.sql , " + getScriptFolderPath() + "load-script-source2.sql"; + private final String CREATE_SQL = getScriptFolderPath() + "create-script-source.sql , " + getScriptFolderPath() + "create-script-source2.sql"; + private final String DROP_SQL = getScriptFolderPath() + "drop-script-source.sql , " + getScriptFolderPath() + "drop-script-source2.sql"; private static int schemagenNumber = 0; @@ -65,12 +67,29 @@ public class JpaSchemaGeneratorTest extends BaseEntityManagerFunctionalTestCase doTest( settings ); } - protected String getResourceUrlString(String resource) { - final URL url = getClass().getClassLoader().getResource( resource ); - if ( url == null ) { - throw new RuntimeException( "Unable to locate requested resource [" + resource + "]" ); + protected String getResourceUrlString(String string) { + return getResourceUrlString( getClass().getClassLoader(), string, URL::toString ); + } + + protected String getResourceUrlString(ClassLoader classLoader, String string, Function transformer) { + final String[] strings = string.split( "\\s*,\\s*" ); + final StringBuilder sb = new StringBuilder( string.length() ); + for ( int i = 0; i < strings.length; i++ ) { + if ( i != 0 ) { + sb.append( ',' ); + } + final String resource = strings[i]; + final URL url = classLoader.getResource( resource ); + if ( url == null ) { + throw new RuntimeException( "Unable to locate requested resource [" + resource + "]" ); + } + sb.append( transformer.apply( url ) ); } - return url.toString(); + return sb.toString(); + } + + protected String toFilePath(String relativePath) { + return getResourceUrlString( Thread.currentThread().getContextClassLoader(), relativePath, URL::getFile ); } @SuppressWarnings("unchecked") @@ -143,6 +162,7 @@ public class JpaSchemaGeneratorTest extends BaseEntityManagerFunctionalTestCase EntityManager em = emf.createEntityManager(); try { Assert.assertNotNull( em.find( Item.class, encodedName() ) ); + Assert.assertNotNull( em.find( Item.class, "multi-file-test" ) ); } finally { em.close(); diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java index 908c50c93e..9b5e0a6748 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java @@ -45,10 +45,6 @@ public class JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest extends JpaSchemaG return toFilePath(super.getDropSqlScript()); } - protected String toFilePath(String relativePath) { - return Thread.currentThread().getContextClassLoader().getResource( relativePath ).getFile(); - } - @Override protected String getResourceUrlString(String resource) { return resource; diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/create-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/create-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/create-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/drop-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/drop-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/drop-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql new file mode 100644 index 0000000000..ae16517d82 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql new file mode 100644 index 0000000000..ae16517d82 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/load-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/load-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/load-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); From 75bcb6bc0c77dd5742e007eeda4009631060a19f Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 18 May 2021 10:13:49 +0200 Subject: [PATCH 39/45] HHH-14616 Add test for issue --- ...cLockWithGloballyQuotedIdentifierTest.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java new file mode 100644 index 0000000000..109b0fc0c4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java @@ -0,0 +1,92 @@ +package org.hibernate.test.optlock; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.LockModeType; +import javax.persistence.Version; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class OptimisticLockWithGloballyQuotedIdentifierTest extends BaseCoreFunctionalTestCase { + + @Override + protected void configure(Configuration configuration) { + configuration.setProperty( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, "true" ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + inTransaction( + session -> { + Person person = new Person( "1", "Fabiana" ); + session.persist( person ); + } + ); + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createQuery( "delete from Person" ).executeUpdate(); + } + ); + } + + @Test + public void testHqlQueryWithOptimisticLock() { + inTransaction( + session -> { + session.createQuery( "from Person e", Person.class ) + .setLockMode( LockModeType.OPTIMISTIC ) + .getResultList().get( 0 ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + private String id; + + @Version + private long version; + + private String name; + + public Person() { + } + + public Person(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} From e76a60cbfc0d556e16301140ba8dbd525a17f813 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 18 May 2021 10:14:22 +0200 Subject: [PATCH 40/45] HHH-14616 Oprimistic Lock throws org.hibernate.exception.SQLGrammarException: could not retrieve version --- .../hibernate/persister/entity/AbstractEntityPersister.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 1a3a43a1c8..a64545ce76 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -166,6 +166,7 @@ public abstract class AbstractEntityPersister private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractEntityPersister.class ); public static final String ENTITY_CLASS = "class"; + public static final String VERSION_COLUMN_ALIAS = "v"; private final NavigableRole navigableRole; @@ -1721,7 +1722,7 @@ public abstract class AbstractEntityPersister SimpleSelect select = new SimpleSelect( getFactory().getDialect() ) .setTableName( getVersionedTableName() ); if ( isVersioned() ) { - select.addColumn( versionColumnName ); + select.addColumn( getVersionColumnName(), VERSION_COLUMN_ALIAS ); } else { select.addColumns( rootTableKeyColumnNames ); @@ -1947,7 +1948,7 @@ public abstract class AbstractEntityPersister if ( !isVersioned() ) { return this; } - return getVersionType().nullSafeGet( rs, getVersionColumnName(), session, null ); + return getVersionType().nullSafeGet( rs, VERSION_COLUMN_ALIAS, session, null ); } finally { session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st ); From 6bb1900495b25aa2d14faa98c2d00b0b24d1f37e Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Wed, 19 May 2021 17:08:08 -0700 Subject: [PATCH 41/45] HHH-14616 : Add test case with default hibernate.globally_quoted_identifiers (=false) and version column quoted --- .../OptimisticLockWithQuotedVersionTest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java new file mode 100644 index 0000000000..6d1bb39a87 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java @@ -0,0 +1,89 @@ +package org.hibernate.test.optlock; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.LockModeType; +import javax.persistence.Version; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class OptimisticLockWithQuotedVersionTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + inTransaction( + session -> { + Person person = new Person( "1", "Fabiana" ); + session.persist( person ); + } + ); + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createQuery( "delete from Person" ).executeUpdate(); + } + ); + } + + @Test + public void testHqlQueryWithOptimisticLock() { + inTransaction( + session -> { + session.createQuery( "from Person e", Person.class ) + .setLockMode( LockModeType.OPTIMISTIC ) + .getResultList().get( 0 ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + private String id; + + @Version + @Column(name = "`version`") + private long version; + + private String name; + + public Person() { + } + + public Person(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} From 26e858c78b303cbb2a0c5539d8a25f879cd3c1c7 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Sat, 22 May 2021 09:12:40 +0200 Subject: [PATCH 42/45] HHH-14616 Change VERSION_COLUMN_ALIAS from v to version_ --- .../org/hibernate/persister/entity/AbstractEntityPersister.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index a64545ce76..53924d8dc9 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -166,7 +166,7 @@ public abstract class AbstractEntityPersister private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractEntityPersister.class ); public static final String ENTITY_CLASS = "class"; - public static final String VERSION_COLUMN_ALIAS = "v"; + public static final String VERSION_COLUMN_ALIAS = "version_"; private final NavigableRole navigableRole; From fc3accfbd1b8596a440837ba7b7c29a875968e68 Mon Sep 17 00:00:00 2001 From: Christoph Dreis Date: Fri, 23 Apr 2021 16:43:04 +0200 Subject: [PATCH 43/45] HHH-14574 Avoid NPEs from LoadContexts.cleanup(ResultSet) --- .../hibernate/engine/loading/internal/LoadContexts.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/loading/internal/LoadContexts.java b/hibernate-core/src/main/java/org/hibernate/engine/loading/internal/LoadContexts.java index 53e6452c27..8c53e64b62 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/loading/internal/LoadContexts.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/loading/internal/LoadContexts.java @@ -78,11 +78,15 @@ public class LoadContexts { public void cleanup(ResultSet resultSet) { if ( collectionLoadContexts != null ) { final CollectionLoadContext collectionLoadContext = collectionLoadContexts.remove( resultSet ); - collectionLoadContext.cleanup(); + if ( collectionLoadContext != null ) { + collectionLoadContext.cleanup(); + } } if ( entityLoadContexts != null ) { final EntityLoadContext entityLoadContext = entityLoadContexts.remove( resultSet ); - entityLoadContext.cleanup(); + if ( entityLoadContext != null ) { + entityLoadContext.cleanup(); + } } } From ad57a1dde26e6e683a941e50206bd8d746ed0e8c Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Mon, 24 May 2021 11:24:50 +0000 Subject: [PATCH 44/45] 5.5.0.CR1 --- changelog.txt | 21 +++++++++++++++++++++ gradle/version.properties | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 05f4fdf969..45a2b4052b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,27 @@ Hibernate 5 Changelog Note: Please refer to JIRA to learn more about each issue. +Changes in 5.5.0.CR1 (May 24, 2021) +------------------------------------------------------------------------------------------------------------------------ + +https://hibernate.atlassian.net/projects/HHH/versions/31942 + +** Bug + * [HHH-14620] - Retrieving a collection from an entity triggers collection initialization (with extended bytecode enhancement enabled) + * [HHH-14619] - ClassCastException because collection of uninitialized proxy is dirty checked + * [HHH-14616] - Optimistic Lock throws org.hibernate.exception.SQLGrammarException: could not retrieve version + * [HHH-14596] - WhereAnnotatedOneToManySizeTest fails on HANA database + +** Improvement + * [HHH-14622] - Improved iteration of PreLoadEventListener + * [HHH-14621] - Introduce new methods on EventListenerGroup which allow Hibernate Reactive to fire events more efficiently + * [HHH-14618] - Having the possibility to include several SQL files into the import.sql file + * [HHH-14574] - Avoid NullPointerExceptions from LoadContexts.cleanup(ResultSet) + +** Task + * [HHH-14610] - Upgrade to Byte Buddy 1.10.22 + + Changes in 5.5.0.Beta1 (May 12, 2021) ------------------------------------------------------------------------------------------------------------------------ diff --git a/gradle/version.properties b/gradle/version.properties index 27307e6e59..fdc8aad41e 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file +hibernateVersion=5.5.0.CR1 \ No newline at end of file From 7570f39d10db832f443db6f0b8b87a10cd6bfec1 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Mon, 24 May 2021 11:31:12 +0000 Subject: [PATCH 45/45] 5.5.0-SNAPSHOT --- gradle/version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/version.properties b/gradle/version.properties index fdc8aad41e..27307e6e59 100644 --- a/gradle/version.properties +++ b/gradle/version.properties @@ -1 +1 @@ -hibernateVersion=5.5.0.CR1 \ No newline at end of file +hibernateVersion=5.5.0-SNAPSHOT \ No newline at end of file