diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c05355..e708b1c023 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 14e30f7416..1f3fdbc528 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c51583..4f906e0c81 100755 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index a9f778a7a9..ac1b06f938 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/naming/CamelCaseToUnderscoresNamingStrategy.java b/hibernate-core/src/main/java/org/hibernate/boot/model/naming/CamelCaseToUnderscoresNamingStrategy.java new file mode 100644 index 0000000000..06e82fbbf7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/naming/CamelCaseToUnderscoresNamingStrategy.java @@ -0,0 +1,92 @@ +/* + * 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.boot.model.naming; + +import java.util.Locale; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; + +/** + * Originally copied from Spring Boot as this strategy is popular there + * (original name is SpringPhysicalNamingStrategy). + * + * @author Phillip Webb + * @author Madhura Bhave + */ +public class CamelCaseToUnderscoresNamingStrategy implements PhysicalNamingStrategy { + + @Override + public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return apply( name, jdbcEnvironment ); + } + + @Override + public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return apply( name, jdbcEnvironment ); + } + + @Override + public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return apply( name, jdbcEnvironment ); + } + + @Override + public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return apply( name, jdbcEnvironment ); + } + + @Override + public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return apply( name, jdbcEnvironment ); + } + + private Identifier apply(final Identifier name, final JdbcEnvironment jdbcEnvironment) { + if ( name == null ) { + return null; + } + StringBuilder builder = new StringBuilder( name.getText().replace( '.', '_' ) ); + for ( int i = 1; i < builder.length() - 1; i++ ) { + if ( isUnderscoreRequired( builder.charAt( i - 1 ), builder.charAt( i ), builder.charAt( i + 1 ) ) ) { + builder.insert( i++, '_' ); + } + } + return getIdentifier( builder.toString(), name.isQuoted(), jdbcEnvironment ); + } + + /** + * Get an identifier for the specified details. By default this method will return an identifier + * with the name adapted based on the result of {@link #isCaseInsensitive(JdbcEnvironment)} + * + * @param name the name of the identifier + * @param quoted if the identifier is quoted + * @param jdbcEnvironment the JDBC environment + * + * @return an identifier instance + */ + protected Identifier getIdentifier(String name, final boolean quoted, final JdbcEnvironment jdbcEnvironment) { + if ( isCaseInsensitive( jdbcEnvironment ) ) { + name = name.toLowerCase( Locale.ROOT ); + } + return new Identifier( name, quoted ); + } + + /** + * Specify whether the database is case sensitive. + * + * @param jdbcEnvironment the JDBC environment which can be used to determine case + * + * @return true if the database is case insensitive sensitivity + */ + protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) { + return true; + } + + private boolean isUnderscoreRequired(final char before, final char current, final char after) { + return Character.isLowerCase( before ) && Character.isUpperCase( current ) && Character.isLowerCase( after ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index 23de31d25e..2e69b9ae81 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -630,7 +630,7 @@ public class StatefulPersistenceContext implements PersistenceContext { private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) { if ( li.getSession() != this.getSession() ) { final EntityPersister persister = session.getFactory().getMetamodel().entityPersister( li.getEntityName() ); - final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister ); + final EntityKey key = session.generateEntityKey( li.getInternalIdentifier(), persister ); // any earlier proxy takes precedence getOrInitializeProxiesByKey().putIfAbsent( key, proxy ); proxy.getHibernateLazyInitializer().setSession( session ); @@ -1338,7 +1338,7 @@ public class StatefulPersistenceContext implements PersistenceContext { ); } if ( found ) { - return proxy.getHibernateLazyInitializer().getIdentifier(); + return proxy.getHibernateLazyInitializer().getInternalIdentifier(); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java index dfa75471e1..1dbcfceabb 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java @@ -52,7 +52,7 @@ public class DefaultEvictEventListener implements EvictEventListener { if ( object instanceof HibernateProxy ) { final LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); - final Object id = li.getIdentifier(); + final Object id = li.getInternalIdentifier(); if ( id == null ) { throw new IllegalArgumentException( "Could not determine identifier of proxy passed to evict()" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index fc43c337ce..e9751b3149 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -103,7 +103,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer(); if ( li.isUninitialized() ) { LOG.trace( "Ignoring uninitialized proxy" ); - event.setResult( source.load( li.getEntityName(), li.getIdentifier() ) ); + event.setResult( source.load( li.getEntityName(), li.getInternalIdentifier() ) ); //EARLY EXIT! return; } 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 75618f249c..9500778773 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -1471,7 +1471,7 @@ public class SessionImpl if ( li.getSession() != this ) { throw new TransientObjectException( "The proxy was not associated with this session" ); } - return li.getIdentifier(); + return li.getInternalIdentifier(); } else { EntityEntry entry = persistenceContext.getEntry( object ); @@ -1499,7 +1499,7 @@ public class SessionImpl } private Object getProxyIdentifier(Object proxy) { - return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getIdentifier(); + return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getInternalIdentifier(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java index 9ece68acc9..bb71b74d4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java @@ -68,7 +68,7 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl } if ( entity instanceof HibernateProxy ) { - return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier(); + return ((HibernateProxy) entity).getHibernateLazyInitializer().getInternalIdentifier(); } else if ( entity instanceof ManagedEntity ) { EntityEntry entityEntry = ((ManagedEntity) entity).$$_hibernate_getEntityEntry(); diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index ae6ad4fd1f..da07df5cb4 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -122,8 +122,8 @@ public class Column implements Selectable, Serializable, Cloneable { if ( lastLetter == -1 ) { alias = "column"; } - else if ( name.length() > lastLetter + 1 ) { - alias = name.substring( 0, lastLetter + 1 ); + else if ( alias.length() > lastLetter + 1 ) { + alias = alias.substring( 0, lastLetter + 1 ); } boolean useRawName = name.length() + suffix.length() <= dialect.getMaxAliasLength() diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java b/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java index 381d67edac..14e0c8d661 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java @@ -81,6 +81,11 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { return entityName; } + @Override + public final Object getInternalIdentifier() { + return id; + } + @Override public final Object getIdentifier() { if ( isUninitialized() && isInitializeProxyWhenAccessingIdentifier() ) { @@ -90,7 +95,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { } private boolean isInitializeProxyWhenAccessingIdentifier() { - return session != null && session.getFactory() + return getSession() != null && getSession().getFactory() .getSessionFactoryOptions() .getJpaCompliance().isJpaProxyComplianceEnabled(); } @@ -256,7 +261,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { public final void initializeWithoutLoadIfPossible() { if ( !initialized && session != null && session.isOpenOrWaitingForAutoClose() ) { final EntityKey key = session.generateEntityKey( - getIdentifier(), + getInternalIdentifier(), session.getFactory().getMetamodel().entityPersister( getEntityName() ) ); final Object entity = session.getPersistenceContextInternal().getEntity( key ); @@ -301,7 +306,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { } private Object getProxyOrNull() { - final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() ); + final EntityKey entityKey = generateEntityKeyOrNull( getInternalIdentifier(), session, getEntityName() ); if ( entityKey != null && session != null && session.isOpenOrWaitingForAutoClose() ) { return session.getPersistenceContextInternal().getProxy( entityKey ); } @@ -322,7 +327,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { @Override public final Object getImplementation(SharedSessionContractImplementor s) throws HibernateException { - final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), s, getEntityName() ); + final EntityKey entityKey = generateEntityKeyOrNull( getInternalIdentifier(), s, getEntityName() ); return ( entityKey == null ? null : s.getPersistenceContext().getEntity( entityKey ) ); } @@ -372,7 +377,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer { } this.readOnly = readOnly; if ( initialized ) { - EntityKey key = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() ); + EntityKey key = generateEntityKeyOrNull( getInternalIdentifier(), session, getEntityName() ); final PersistenceContext persistenceContext = session.getPersistenceContext(); if ( key != null && persistenceContext.containsEntity( key ) ) { persistenceContext.setReadOnly( target, readOnly ); diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/LazyInitializer.java b/hibernate-core/src/main/java/org/hibernate/proxy/LazyInitializer.java index f03cc384fa..d3f7114e7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/LazyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/LazyInitializer.java @@ -28,6 +28,17 @@ public interface LazyInitializer { * * @return The identifier value. */ + default Object getInternalIdentifier() { + return getIdentifier(); + } + + /** + * Retrieve the identifier value for the entity our owning proxy represents. + * + * When JPA proxy compliance is enabled the proxy is initialized. + * + * @return The identifier value. + */ Object getIdentifier(); /** diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/map/MapProxy.java b/hibernate-core/src/main/java/org/hibernate/proxy/map/MapProxy.java index de6e2a2eb4..448f5c9b2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/map/MapProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/map/MapProxy.java @@ -116,7 +116,7 @@ public class MapProxy implements HibernateProxy, Map, Serializable { private Object serializableProxy() { return new SerializableMapProxy( li.getEntityName(), - li.getIdentifier(), + li.getInternalIdentifier(), ( li.isReadOnlySettingAvailable() ? Boolean.valueOf( li.isReadOnly() ) : li.isReadOnlyBeforeAttachedToSession() ), li.getSessionFactoryUuid(), li.isAllowLoadOutsideTransaction() diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyInterceptor.java b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyInterceptor.java index c9cd7c29f5..edcbf509d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyInterceptor.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyInterceptor.java @@ -84,7 +84,7 @@ public class ByteBuddyInterceptor extends BasicLazyInitializer implements ProxyC getEntityName(), persistentClass, interfaces, - getIdentifier(), + getInternalIdentifier(), ( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ), getSessionFactoryUuid(), isAllowLoadOutsideTransaction(), diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index 340f1e6db5..43f66466e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -214,7 +214,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { id = entity; } else if ( HibernateProxy.class.isInstance( entity ) ) { - id = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); + id = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier(); } else { if ( idGetter == null ) { @@ -451,7 +451,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { if ( entity instanceof HibernateProxy ) { // entity is a proxy, so we know it is not transient; just return ID from proxy - return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); + return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier(); } if ( session != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index a2507b3f42..8abfafe16d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -335,7 +335,7 @@ public abstract class EntityType extends AbstractType implements AssociationType final Object id; if ( x instanceof HibernateProxy ) { - id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier(); + id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getInternalIdentifier(); } else { final Class mappedClass = persister.getMappedClass(); @@ -365,7 +365,7 @@ public abstract class EntityType extends AbstractType implements AssociationType Object xid; if ( x instanceof HibernateProxy ) { xid = ( (HibernateProxy) x ).getHibernateLazyInitializer() - .getIdentifier(); + .getInternalIdentifier(); } else { if ( mappedClass.isAssignableFrom( x.getClass() ) ) { @@ -379,7 +379,8 @@ public abstract class EntityType extends AbstractType implements AssociationType Object yid; if ( y instanceof HibernateProxy ) { - yid = ( (HibernateProxy) y ).getHibernateLazyInitializer().getIdentifier(); + yid = ( (HibernateProxy) y ).getHibernateLazyInitializer() + .getInternalIdentifier(); } else { if ( mappedClass.isAssignableFrom( y.getClass() ) ) { @@ -523,7 +524,7 @@ public abstract class EntityType extends AbstractType implements AssociationType final Object id; if ( value instanceof HibernateProxy ) { HibernateProxy proxy = (HibernateProxy) value; - id = proxy.getHibernateLazyInitializer().getIdentifier(); + id = proxy.getHibernateLazyInitializer().getInternalIdentifier(); } else { id = persister.getIdentifier( value ); diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/ops/MergeJpaComplianceTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/ops/MergeJpaComplianceTest.java new file mode 100644 index 0000000000..1da7fd5534 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/ops/MergeJpaComplianceTest.java @@ -0,0 +1,211 @@ +package org.hibernate.jpa.test.ops; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil2.fromTransaction; +import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction; + +@TestForIssue( jiraKey = "HHH-14608") +public class MergeJpaComplianceTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Person.class, Occupation.class, PersonOccupation.class + }; + } + + @Override + protected void addConfigOptions(Map config) { + config.put( org.hibernate.cfg.AvailableSettings.JPA_PROXY_COMPLIANCE, true ); + } + + @Test + public void testMerge() { + Person person = fromTransaction( + entityManagerFactory(), + entityManager -> { + Person p; + p = new Person( "1", "Fab" ); + Occupation t = new Occupation( 1l, "Some work" ); + + entityManager.persist( p ); + entityManager.persist( t ); + + entityManager.flush(); + + PersonOccupation participant = new PersonOccupation( p, t ); + entityManager.persist( participant ); + return p; + } + ); + + inTransaction( + entityManagerFactory(), + entityManager -> { + person.setName( "Fabiana" ); + entityManager.merge( person ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + private String id; + + private String name; + + @OneToMany(mappedBy = "pk.person", cascade = CascadeType.ALL, orphanRemoval = true) + private List occupations; + + public Person() { + + } + + public Person(String id, String name) { + this.id = id; + this.name = name; + } + + protected void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List getOccupations() { + return occupations; + } + + protected void addOccupationPeoplet(PersonOccupation personOccupation) { + if ( this.occupations == null ) { + occupations = new ArrayList<>(); + } + this.occupations.add( personOccupation ); + personOccupation.getPk().setPerson( this ); + } + + protected void setOccupations(List occupations) { + this.occupations = occupations; + } + } + + @Entity(name = "Occupation") + public static class Occupation { + @Id + private long id; + + private String name; + + @OneToMany(mappedBy = "pk.occupation", cascade = CascadeType.ALL) + private List personOccupations; + + protected Occupation() { + } + + public Occupation(long id, String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + protected void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + protected void setName(String name) { + this.name = name; + } + + public List getPersonOccupations() { + return personOccupations; + } + + protected void addPersonOccupation(PersonOccupation participant) { + if ( personOccupations == null ) { + personOccupations = new ArrayList<>(); + } + personOccupations.add( participant ); + participant.getPk().setOccupation( this ); + } + + protected void setPersonOccupations(List personOccupations) { + this.personOccupations = personOccupations; + } + } + + @Entity(name = "PersonOccupation") + public static class PersonOccupation { + @EmbeddedId + private PersonOccupationPK pk = new PersonOccupationPK(); + + protected PersonOccupation() { + } + + public PersonOccupation(Person person, Occupation occupation) { + person.addOccupationPeoplet( this ); + occupation.addPersonOccupation( this ); + } + + public PersonOccupationPK getPk() { + return pk; + } + + public void setPk(PersonOccupationPK pk) { + this.pk = pk; + } + } + + @Embeddable + public static class PersonOccupationPK implements Serializable { + + @ManyToOne(fetch = FetchType.LAZY) + private Person person; + + @ManyToOne(fetch = FetchType.LAZY) + private Occupation occupation; + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public Occupation getOccupation() { + return occupation; + } + + public void setOccupation(Occupation occupation) { + this.occupation = occupation; + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Company.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Company.java new file mode 100644 index 0000000000..533f9251b2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Company.java @@ -0,0 +1,25 @@ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Company { + @Id + private Long id; + + @Override + public String toString() { + return "Company{" + + "id=" + id + + '}'; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/CostCenter.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/CostCenter.java new file mode 100644 index 0000000000..c47eccf766 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/CostCenter.java @@ -0,0 +1,39 @@ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class CostCenter { + @Id + private Long id; + + @ManyToOne(optional = false) + private Company company; + + @Override + public String toString() { + return "CostCenter{" + + "id=" + id + + ", company=" + company + + '}'; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Company getCompany() { + return company; + } + + public void setCompany(Company company) { + this.company = company; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest.java new file mode 100644 index 0000000000..689bb21f81 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest.java @@ -0,0 +1,191 @@ +/* + * 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 http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import org.hibernate.Hibernate; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.loader.BatchFetchStyle.PADDED; + +/** + * Test lazy-to-one initialization within a collection initialization, + * with the PADDED batch-fetch-style. + *

+ * In particular, with Offer having a lazy to-one association to CostCenter, + * and User having a lazy to-many association to UserAuthorization1 and UserAuthorization2, + * and UserAuthorization1 and UserAuthorization2 having an EAGER association to CostCenter, + * test: + *

    + *
  • Get a reference to Offer (which will create an uninitialized proxy for CostCenter)
  • + *
  • Get a reference to User
  • + *
  • Initialize User's collection containing UserAuthorization1 and UserAuthorization2, + * which will initialize CostCenter DURING the loading, + * which used to fail because we tried to initialize CostCenter twice + * (once for UserAuthorization1, and once for UserAuthorization2)
  • + *
+ */ +@RunWith(BytecodeEnhancerRunner.class) +@TestForIssue(jiraKey = "HHH-14730") +public class InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest + extends BaseNonConfigCoreFunctionalTestCase { + + @Override + protected void applyMetadataSources(MetadataSources sources) { + super.applyMetadataSources( sources ); + sources.addAnnotatedClass( User.class ); + sources.addAnnotatedClass( UserAuthorization.class ); + sources.addAnnotatedClass( Company.class ); + sources.addAnnotatedClass( CostCenter.class ); + sources.addAnnotatedClass( Offer.class ); + } + + @Override + protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { + super.configureStandardServiceRegistryBuilder( ssrb ); + ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, true ); + ssrb.applySetting( AvailableSettings.BATCH_FETCH_STYLE, PADDED ); + ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, 10 ); + } + + @Override + protected void afterSessionFactoryBuilt(SessionFactoryImplementor sessionFactory) { + inTransaction( session -> { + User user0 = new User(); + user0.setId( 0L ); + session.persist( user0 ); + + User user1 = new User(); + user1.setId( 1L ); + session.persist( user1 ); + + User user2 = new User(); + user2.setId( 2L ); + session.persist( user2 ); + + Company company = new Company(); + company.setId( 2L ); + session.persist( company ); + + CostCenter costCenter = new CostCenter(); + costCenter.setId( 3L ); + costCenter.setCompany( company ); + session.persist( costCenter ); + + UserAuthorization user0Authorization1 = new UserAuthorization(); + user0Authorization1.setId( 1L ); + user0Authorization1.setUser( user0 ); + user0Authorization1.setCostCenter( costCenter ); + session.persist( user0Authorization1 ); + + UserAuthorization user1Authorization1 = new UserAuthorization(); + user1Authorization1.setId( 11L ); + user1Authorization1.setUser( user1 ); + user1Authorization1.setCostCenter( costCenter ); + session.persist( user1Authorization1 ); + + UserAuthorization user1Authorization2 = new UserAuthorization(); + user1Authorization2.setId( 12L ); + user1Authorization2.setUser( user1 ); + user1Authorization2.setCostCenter( costCenter ); + session.persist( user1Authorization2 ); + + UserAuthorization user2Authorization1 = new UserAuthorization(); + user2Authorization1.setId( 21L ); + user2Authorization1.setUser( user2 ); + user2Authorization1.setCostCenter( costCenter ); + session.persist( user2Authorization1 ); + + UserAuthorization user2Authorization2 = new UserAuthorization(); + user2Authorization2.setId( 22L ); + user2Authorization2.setUser( user2 ); + user2Authorization2.setCostCenter( costCenter ); + session.persist( user2Authorization2 ); + + UserAuthorization user2Authorization3 = new UserAuthorization(); + user2Authorization3.setId( 23L ); + user2Authorization3.setUser( user2 ); + user2Authorization3.setCostCenter( costCenter ); + session.persist( user2Authorization3 ); + + Offer offer = new Offer(); + offer.setId( 6L ); + offer.setCostCenter( costCenter ); + session.persist( offer ); + } ); + } + + @Test + public void testOneReference() { + inTransaction( (session) -> { + // Add a lazy proxy of the cost center to the persistence context + // through the lazy to-one association from the offer. + Offer offer = session.find( Offer.class, 6L ); + + User user = session.find( User.class, 0L ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); + + // Trigger lazy-loading of the cost center + // through the loading of the authorization, + // which contains an eager reference to the cost center. + assertThat( user.getAuthorizations().size() ).isEqualTo( 1 ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); + } ); + } + + @Test + public void testTwoReferences() { + inTransaction( (session) -> { + // Add a lazy proxy of the cost center to the persistence context + // through the lazy to-one association from the offer. + Offer offer = session.find( Offer.class, 6L ); + + User user = session.find( User.class, 1L ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); + + // Trigger lazy-loading of the cost center + // through the loading of the 2 authorizations, + // which both contain an eager reference to the cost center. + assertThat( user.getAuthorizations().size() ).isEqualTo( 2 ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); + } ); + } + + @Test + public void testThreeReferences() { + inTransaction( (session) -> { + // Add a lazy proxy of the cost center to the persistence context + // through the lazy to-one association from the offer. + Offer offer = session.find( Offer.class, 6L ); + + User user = session.find( User.class, 2L ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); + + // Trigger lazy-loading of the cost center + // through the loading of the 3 authorizations, + // which all contain an eager reference to the cost center. + assertThat( user.getAuthorizations().size() ).isEqualTo( 3 ); + + assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Offer.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Offer.java new file mode 100644 index 0000000000..676d77305b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Offer.java @@ -0,0 +1,39 @@ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import static javax.persistence.FetchType.LAZY; + +@Entity +public class Offer { + @Id + private Long id; + + @ManyToOne(fetch = LAZY, optional = false) + private CostCenter costCenter; + + @Override + public String toString() { + return "Offer{" + + "id=" + getId() + + '}'; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public CostCenter getCostCenter() { + return costCenter; + } + + public void setCostCenter(CostCenter costCenter) { + this.costCenter = costCenter; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/User.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/User.java new file mode 100644 index 0000000000..20fdaa9661 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/User.java @@ -0,0 +1,43 @@ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import static javax.persistence.CascadeType.ALL; + +@Entity +@Table(name = "users") +public class User { + @Id + private Long id; + + @OneToMany(mappedBy = "user", cascade = ALL, orphanRemoval = true) + private List authorizations = new ArrayList<>(); + + @Override + public String toString() { + return "User{" + + "id='" + getId() + '\'' + + '}'; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getAuthorizations() { + return authorizations; + } + + public void setAuthorizations(List authorizations) { + this.authorizations = authorizations; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/UserAuthorization.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/UserAuthorization.java new file mode 100644 index 0000000000..5386fa65ab --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/UserAuthorization.java @@ -0,0 +1,49 @@ +package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class UserAuthorization { + @Id + private Long id; + + @ManyToOne(optional = false) + private User user; + + @ManyToOne(optional = false) + private CostCenter costCenter; + + @Override + public String toString() { + return "UserAuthorization{" + + "id='" + getId() + '\'' + + '}'; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public CostCenter getCostCenter() { + return costCenter; + } + + public void setCostCenter(CostCenter costCenter) { + this.costCenter = costCenter; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/mapping/ColumnLastIndexNotLetterAliasTest.java b/hibernate-core/src/test/java/org/hibernate/test/mapping/ColumnLastIndexNotLetterAliasTest.java new file mode 100644 index 0000000000..5797636f88 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/mapping/ColumnLastIndexNotLetterAliasTest.java @@ -0,0 +1,45 @@ +/* + * 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.mapping; + +import java.util.Locale; + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.PostgreSQL94Dialect; +import org.hibernate.mapping.Column; + +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Aliases should always be lower-case. This tests that an alias for + * a column name that ends in a character that is not a letter gets + * generated to be all in lower-case. + * + * @author Gail Badner + */ +public class ColumnLastIndexNotLetterAliasTest { + // Arbitrarily choose PostgreSQL + private static final Dialect DIALECT = new PostgreSQL94Dialect();; + + @Test + @TestForIssue(jiraKey = "HHH-14720") + public void testColumnNameEndinWithNonCharacter() { + test( "aColumn1" ); + test( "aColumn_" ); + test( "aVeryVeryVeryLongColumnName1" ); + test( "aVeryVeryVeryLongColumnName_" ); + } + + private void test(String columnName) { + final Column column = new Column( columnName ); + final String alias = column.getAlias( DIALECT ); + assertEquals( alias.toLowerCase( Locale.ROOT ), alias ); + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/BaseEnversEventListener.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/BaseEnversEventListener.java index cdde5ae744..a6a5d8a4d4 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/BaseEnversEventListener.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/spi/BaseEnversEventListener.java @@ -94,7 +94,7 @@ public abstract class BaseEnversEventListener implements EnversListener { if ( value instanceof HibernateProxy ) { final HibernateProxy hibernateProxy = (HibernateProxy) value; - id = hibernateProxy.getHibernateLazyInitializer().getIdentifier(); + id = hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); // We've got to initialize the object from the proxy to later read its state. value = EntityTools.getTargetFromProxy( session.getFactory(), hibernateProxy ); // HHH-7249 diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/EntityInstantiator.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/EntityInstantiator.java index 506046ca35..5281429432 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/EntityInstantiator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/EntityInstantiator.java @@ -111,7 +111,7 @@ public class EntityInstantiator { final HibernateProxy hibernateProxy = (HibernateProxy) value; final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer(); final String entityName = initializer.getEntityName(); - final Object entityId = initializer.getIdentifier(); + final Object entityId = initializer.getInternalIdentifier(); if ( enversService.getEntitiesConfigurations().isVersioned( entityName ) ) { final String entityClassName = enversService.getEntitiesConfigurations().get( entityName ).getEntityClassName(); final Class entityClass = ReflectionTools.loadClass( diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/SingleIdMapper.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/SingleIdMapper.java index fd65a972b3..b7690a953b 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/SingleIdMapper.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/SingleIdMapper.java @@ -88,7 +88,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu if ( data instanceof HibernateProxy ) { final HibernateProxy hibernateProxy = (HibernateProxy) data; - return hibernateProxy.getHibernateLazyInitializer().getIdentifier(); + return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); } else { return AccessController.doPrivileged( @@ -122,7 +122,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu else { if ( obj instanceof HibernateProxy ) { final HibernateProxy hibernateProxy = (HibernateProxy) obj; - data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getIdentifier() ); + data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() ); } else { final Object value = AccessController.doPrivileged( diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/VirtualEntitySingleIdMapper.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/VirtualEntitySingleIdMapper.java index 26ec6d35db..46de765f3a 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/VirtualEntitySingleIdMapper.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/VirtualEntitySingleIdMapper.java @@ -155,7 +155,7 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper { else { if ( obj instanceof HibernateProxy ) { final HibernateProxy proxy = (HibernateProxy) obj; - data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getIdentifier() ); + data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() ); } else { final Object value = AccessController.doPrivileged( diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/EntityTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/EntityTools.java index 31ad7a29b0..a589869729 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/EntityTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/EntityTools.java @@ -33,7 +33,7 @@ public abstract class EntityTools { if ( obj instanceof HibernateProxy ) { final HibernateProxy hibernateProxy = (HibernateProxy) obj; - return hibernateProxy.getHibernateLazyInitializer().getIdentifier(); + return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); } return session.getEntityPersister( entityName, obj ).getIdentifier( obj, session ); @@ -51,7 +51,7 @@ public abstract class EntityTools { try { return tempSession.get( proxy.getHibernateLazyInitializer().getEntityName(), - proxy.getHibernateLazyInitializer().getIdentifier() + proxy.getHibernateLazyInitializer().getInternalIdentifier() ); } finally { diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/query/internal/impl/RevisionsOfEntityQuery.java b/hibernate-envers/src/main/java/org/hibernate/envers/query/internal/impl/RevisionsOfEntityQuery.java index 78f9f24dd6..43d0a81fec 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/query/internal/impl/RevisionsOfEntityQuery.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/query/internal/impl/RevisionsOfEntityQuery.java @@ -80,7 +80,7 @@ public class RevisionsOfEntityQuery extends AbstractAuditQuery { Object revisionInfoObject = ( (Map) versionsEntity.get( originalId ) ).get( revisionPropertyName ); if ( revisionInfoObject instanceof HibernateProxy ) { - return (Number) ( (HibernateProxy) revisionInfoObject ).getHibernateLazyInitializer().getIdentifier(); + return (Number) ( (HibernateProxy) revisionInfoObject ).getHibernateLazyInitializer().getInternalIdentifier(); } else { // Not a proxy - must be read from cache or with a join diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/proxy/ProxyIdentifier.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/proxy/ProxyIdentifier.java index 0e863bdb91..293cb77a7a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/proxy/ProxyIdentifier.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/proxy/ProxyIdentifier.java @@ -114,8 +114,8 @@ public class ProxyIdentifier extends BaseEnversJPAFunctionalTestCase { LazyInitializer lazyInitializer = proxyCreateByEnvers.getHibernateLazyInitializer(); Assert.assertTrue( lazyInitializer.isUninitialized() ); - Assert.assertNotNull( lazyInitializer.getIdentifier() ); - Assert.assertEquals( tnae1.getId(), lazyInitializer.getIdentifier() ); + Assert.assertNotNull( lazyInitializer.getInternalIdentifier() ); + Assert.assertEquals( tnae1.getId(), lazyInitializer.getInternalIdentifier() ); Assert.assertTrue( lazyInitializer.isUninitialized() ); Assert.assertEquals( uste1.getId(), rev1.getReference().getId() ); diff --git a/hibernate-integrationtest-java-modules/hibernate-integrationtest-java-modules.gradle b/hibernate-integrationtest-java-modules/hibernate-integrationtest-java-modules.gradle index fe53f83283..74a13c116c 100644 --- a/hibernate-integrationtest-java-modules/hibernate-integrationtest-java-modules.gradle +++ b/hibernate-integrationtest-java-modules/hibernate-integrationtest-java-modules.gradle @@ -9,34 +9,10 @@ description = 'Integration tests for running Hibernate ORM in the Java module pa apply from: rootProject.file( 'gradle/java-module.gradle' ) +// See https://docs.gradle.org/6.7.1/userguide/java_testing.html#blackbox_integration_testing +// See https://docs.gradle.org/6.7.1/samples/sample_java_modules_multi_project_with_integration_tests.html java.modularity.inferModulePath = true -// In this module, the "main" code is actually just test code that happens -// to be built independently so as to generate a Java module. -// So, let's override settings for compilation of the main code, just for this particular case. -def testJavaVersions = gradle.ext.javaVersions.test -tasks.compileJava { - if ( !gradle.ext.javaToolchainEnabled ) { - sourceCompatibility = JavaVersion.toVersion( testJavaVersions.release ) - targetCompatibility = JavaVersion.toVersion( testJavaVersions.release ) - } - else { - javaCompiler = javaToolchains.compilerFor { - languageVersion = testJavaVersions.compiler - } - - // Remove JDK8-only options (if any) that are incompatible with options.release - for ( it = options.compilerArgs.listIterator(); it.hasNext(); ) { - if ( it.next() in ['-source', '-target'] ) { - it.remove() - it.next() - it.remove() - } - } - - options.release = testJavaVersions.release.asInt() - } -} // Checkstyle fails for module-info checkstyleMain.exclude '**/module-info.java' @@ -44,6 +20,7 @@ checkstyleMain.exclude '**/module-info.java' dependencies { api project( ':hibernate-core' ) api project( ':hibernate-envers' ) + api libraries.jpa implementation libraries.jpa } diff --git a/hibernate-integrationtest-java-modules/src/main/java/module-info.java b/hibernate-integrationtest-java-modules/src/main/java/module-info.java deleted file mode 100644 index 51a8fc6533..0000000000 --- a/hibernate-integrationtest-java-modules/src/main/java/module-info.java +++ /dev/null @@ -1,27 +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 . - */ -module org.hibernate.orm.integrationtest.java.module { - exports org.hibernate.orm.integrationtest.java.module.service; - opens org.hibernate.orm.integrationtest.java.module.entity to - org.hibernate.orm.core; - - requires java.persistence; - /* - * IDEA will not find the modules below because it apparently doesn't support automatic module names - * for modules in the current project. - * Everything should work fine when building from the command line, though. - */ - requires org.hibernate.orm.core; - requires org.hibernate.orm.envers; - - /* - * This is necessary in order to use SessionFactory, - * which extends "javax.naming.Referenceable". - * Without this, compilation as a Java module fails. - */ - requires java.naming; -} \ No newline at end of file diff --git a/hibernate-integrationtest-java-modules/src/test/java/module-info.java b/hibernate-integrationtest-java-modules/src/test/java/module-info.java new file mode 100644 index 0000000000..c13f00f960 --- /dev/null +++ b/hibernate-integrationtest-java-modules/src/test/java/module-info.java @@ -0,0 +1,33 @@ +/* + * 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 . + */ +module org.hibernate.orm.integrationtest.java.module.test { + + /* + * Main configuration, necessary for real client applications. + */ + + opens org.hibernate.orm.integrationtest.java.module.test.entity to + org.hibernate.orm.core; + + requires java.persistence; + // IDEA will not find the modules below because it apparently doesn't support automatic module names + // for modules in the current project. + // Everything should work fine when building from the command line, though. + requires org.hibernate.orm.core; + requires org.hibernate.orm.envers; + + // Transitive dependencies that leak through the Hibernate ORM API + requires java.sql; + requires java.naming; // SessionFactory extends "javax.naming.Referenceable" + + /* + * Test-only configuration. + */ + + opens org.hibernate.orm.integrationtest.java.module.test to junit; + requires junit; +} \ No newline at end of file diff --git a/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/JavaModulePathIT.java b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/JavaModulePathIT.java index 6476bfd65c..815462f249 100644 --- a/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/JavaModulePathIT.java +++ b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/JavaModulePathIT.java @@ -11,7 +11,7 @@ import java.util.Arrays; import org.hibernate.Session; import org.hibernate.envers.boot.internal.EnversIntegrator; -import org.hibernate.orm.integrationtest.java.module.service.AuthorService; +import org.hibernate.orm.integrationtest.java.module.test.service.AuthorService; import org.junit.Assert; import org.junit.Test; diff --git a/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/ScannerTest.java b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/ScannerTest.java index 7e00d53bd9..d26f30827d 100644 --- a/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/ScannerTest.java +++ b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/ScannerTest.java @@ -15,7 +15,7 @@ import org.hibernate.boot.archive.scan.internal.StandardScanParameters; import org.hibernate.boot.archive.scan.internal.StandardScanner; import org.hibernate.boot.archive.scan.spi.ClassDescriptor; import org.hibernate.boot.archive.scan.spi.ScanResult; -import org.hibernate.orm.integrationtest.java.module.entity.Author; +import org.hibernate.orm.integrationtest.java.module.test.entity.Author; import org.junit.Assert; import org.junit.Test; diff --git a/hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/entity/Author.java b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/entity/Author.java similarity index 93% rename from hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/entity/Author.java rename to hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/entity/Author.java index ac7706ef59..143ef766d9 100644 --- a/hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/entity/Author.java +++ b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/entity/Author.java @@ -4,7 +4,7 @@ * 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.orm.integrationtest.java.module.entity; +package org.hibernate.orm.integrationtest.java.module.test.entity; import javax.persistence.Basic; import javax.persistence.Entity; diff --git a/hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/service/AuthorService.java b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/service/AuthorService.java similarity index 95% rename from hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/service/AuthorService.java rename to hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/service/AuthorService.java index 8f9c3ec40f..a3a98ecd64 100644 --- a/hibernate-integrationtest-java-modules/src/main/java/org/hibernate/orm/integrationtest/java/module/service/AuthorService.java +++ b/hibernate-integrationtest-java-modules/src/test/java/org/hibernate/orm/integrationtest/java/module/test/service/AuthorService.java @@ -4,7 +4,7 @@ * 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.orm.integrationtest.java.module.service; +package org.hibernate.orm.integrationtest.java.module.test.service; import java.util.List; @@ -14,7 +14,7 @@ import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.envers.AuditReader; import org.hibernate.envers.AuditReaderFactory; -import org.hibernate.orm.integrationtest.java.module.entity.Author; +import org.hibernate.orm.integrationtest.java.module.test.entity.Author; public class AuthorService implements AutoCloseable { diff --git a/hibernate-integrationtest-java-modules/src/main/resources/META-INF/persistence.xml b/hibernate-integrationtest-java-modules/src/test/resources/META-INF/persistence.xml similarity index 93% rename from hibernate-integrationtest-java-modules/src/main/resources/META-INF/persistence.xml rename to hibernate-integrationtest-java-modules/src/test/resources/META-INF/persistence.xml index 9108b2e832..810b4f2d9c 100644 --- a/hibernate-integrationtest-java-modules/src/main/resources/META-INF/persistence.xml +++ b/hibernate-integrationtest-java-modules/src/test/resources/META-INF/persistence.xml @@ -10,7 +10,7 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> - org.hibernate.orm.integrationtest.java.module.entity.Author + org.hibernate.orm.integrationtest.java.module.test.entity.Author