Merge branch 'main' into wip/6.0

This commit is contained in:
Andrea Boriero 2021-07-16 11:24:53 +02:00
commit 98e64579fa
40 changed files with 830 additions and 111 deletions

Binary file not shown.

View File

@ -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

2
gradlew vendored
View File

@ -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

21
gradlew.bat vendored
View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 );
}
}

View File

@ -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();
}
}
}

View File

@ -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()" );
}

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -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()

View File

@ -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 );

View File

@ -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();
/**

View File

@ -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()

View File

@ -84,7 +84,7 @@ public class ByteBuddyInterceptor extends BasicLazyInitializer implements ProxyC
getEntityName(),
persistentClass,
interfaces,
getIdentifier(),
getInternalIdentifier(),
( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
getSessionFactoryUuid(),
isAllowLoadOutsideTransaction(),

View File

@ -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 ) {

View File

@ -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 );

View File

@ -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<PersonOccupation> 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<PersonOccupation> 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<PersonOccupation> 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<PersonOccupation> 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<PersonOccupation> 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<PersonOccupation> 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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.
* <p>
* 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:
* <ul>
* <li>Get a reference to Offer (which will create an uninitialized proxy for CostCenter)</li>
* <li>Get a reference to User</li>
* <li>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)</li>
* </ul>
*/
@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();
} );
}
}

View File

@ -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;
}
}

View File

@ -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<UserAuthorization> 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<UserAuthorization> getAuthorizations() {
return authorizations;
}
public void setAuthorizations(List<UserAuthorization> authorizations) {
this.authorizations = authorizations;
}
}

View File

@ -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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 );
}
}

View File

@ -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

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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 {

View File

@ -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

View File

@ -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() );

View File

@ -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
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 {

View File

@ -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">
<persistence-unit name="primaryPU">
<class>org.hibernate.orm.integrationtest.java.module.entity.Author</class>
<class>org.hibernate.orm.integrationtest.java.module.test.entity.Author</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>