Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.hibernate.boot.models.annotations.internal.JoinColumnJpaAnnotation;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.models.spi.MemberDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Properties;

import org.hibernate.boot.BootLogging;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.ParameterizedType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.hibernate.boot.models.annotations.spi.DialectOverrider;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.SourceModelBuildingContext;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.SourceModelBuildingContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
package org.hibernate.boot.model.internal;

import java.util.Collections;
import java.util.Map;

import org.hibernate.AnnotationException;
Expand All @@ -15,7 +14,6 @@
import org.hibernate.MappingException;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.util.LockModeConverter;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.HibernateHints;
import org.hibernate.jpa.LegacySpecHints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,21 @@ private void evictCache(Object entity, EntityPersister persister, EventSource se
}
}

private Object getIdentifier(EventSource session, Object obj) {
Object id = null;
if ( obj != null ) {
id = session.getContextEntityIdentifier( obj );
private Object getIdentifier(EventSource session, Object object) {
if ( object != null ) {
final Object id = session.getContextEntityIdentifier( object );
if ( id == null ) {
final EntityPersister persister = session.getFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor( obj.getClass() );
id = persister.getIdentifier( obj, session );
return session.getFactory().getMappingMetamodel()
.getEntityDescriptor( object.getClass() )
.getIdentifier( object, session );
}
else {
return id;
}
}
else {
return null;
}
return id;
}

private void evict(Object id, CollectionPersister collectionPersister, EventSource session) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,11 @@ public static boolean isTransient(
* Return the identifier of the persistent or transient object, or throw
* an exception if the instance is "unsaved"
* <p>
* Used by OneToOneType and ManyToOneType to determine what id value should
* Used by {@link org.hibernate.type.OneToOneType} and
* {@link org.hibernate.type.ManyToOneType} to determine what id value should
* be used for an object that may or may not be associated with the session.
* This does a "best guess" using any/all info available to use (not just the
* EntityEntry).
* {@link EntityEntry}).
*
* @param entityName The name of the entity
* @param object The entity instance
Expand All @@ -357,9 +358,9 @@ public static Object getEntityIdentifierIfNotUnsaved(
else {
final Object id = session.getContextEntityIdentifier( object );
if ( id == null ) {
// context-entity-identifier returns null explicitly if the entity
// is not associated with the persistence context; so make some
// deeper checks...
// context-entity-identifier always returns null if the
// entity is not associated with the persistence context;
// so make some deeper checks...
throwIfTransient( entityName, object, session );
return session.getEntityPersister( entityName, object ).getIdentifier( object, session );
}
Expand All @@ -369,6 +370,21 @@ public static Object getEntityIdentifierIfNotUnsaved(
}
}

public static Object getEntityIdentifier(
final String entityName,
final Object object,
final SharedSessionContractImplementor session) {
if ( object == null ) {
return null;
}
else {
final Object id = session.getContextEntityIdentifier( object );
return id == null
? session.getEntityPersister( entityName, object ).getIdentifier( object, session )
: id;
}
}

private static void throwIfTransient(String entityName, Object object, SharedSessionContractImplementor session) {
if ( isTransient( entityName, object, Boolean.FALSE, session ) ) {
throw new TransientObjectException( "Entity references an unsaved transient instance of '"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1583,14 +1583,14 @@ protected void registerPossibleUniqueKeyEntries(
final Type type = entry.getPropertyType();

// polymorphism not really handled completely correctly,
// perhaps...well, actually its ok, assuming that the
// perhaps...well, actually it's ok, assuming that the
// entity name used in the lookup is the same as the
// one used here, which it will be

if ( resolvedEntityState[index] != null ) {
final Object key;
if ( type instanceof ManyToOneType manyToOneType ) {
key = ForeignKeys.getEntityIdentifierIfNotUnsaved(
key = ForeignKeys.getEntityIdentifier(
manyToOneType.getAssociatedEntityName(),
resolvedEntityState[index],
session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,9 @@ public String getPropertyName() {
@Override
public boolean isNull(Object owner, SharedSessionContractImplementor session) {
if ( propertyName != null ) {
final EntityPersister ownerPersister = session.getFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor( entityName );
final EntityPersister ownerPersister =
session.getFactory().getMappingMetamodel()
.getEntityDescriptor( entityName );
final Object id = session.getContextEntityIdentifier( owner );
final EntityKey entityKey = session.generateEntityKey( id, ownerPersister );
return session.getPersistenceContextInternal().isPropertyNull( entityKey, getPropertyName() );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.bytecode.enhancement.batch;

import jakarta.persistence.*;
import org.hibernate.Hibernate;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.orm.junit.*;
import org.junit.jupiter.api.Test;

import java.util.Objects;
import java.util.UUID;

import static jakarta.persistence.FetchType.LAZY;
import static org.assertj.core.api.Assertions.assertThat;

@DomainModel(
annotatedClasses = {
HandleVersionNumbersInitializedToNegativeValueTests.RootEntity.class,
HandleVersionNumbersInitializedToNegativeValueTests.ChildEntity.class
}
)
@ServiceRegistry(
settings = {
// For your own convenience to see generated queries:
@Setting(name = AvailableSettings.SHOW_SQL, value = "true"),
@Setting(name = AvailableSettings.FORMAT_SQL, value = "true"),
}
)
@SessionFactory
class HandleVersionNumbersInitializedToNegativeValueTests {

@Test @JiraKey("HHH-18883")
void hhh18883Test(SessionFactoryScope scope) {
var id = UUID.randomUUID();
scope.inTransaction(session -> {
RootEntity rootEntity = new RootEntity(id, new ChildEntity());
session.persist(rootEntity);
});

scope.inTransaction(session -> {
RootEntity rootEntity = session.find(RootEntity.class, id);
assertThat(rootEntity).isNotNull();
assertThat(rootEntity.getChildEntity()).isNotNull();
});
}


@Entity
@Table
public static class RootEntity {

@Id
private UUID id;

@OneToOne(mappedBy = "rootEntity", cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private ChildEntity childEntity;

@Version
private int version = -1;

public RootEntity() {
}

public RootEntity(UUID id, ChildEntity childEntity) {
setId(id);
setChildEntity(childEntity);
}

public UUID getId() {
return id;
}

public void setId(UUID id) {
this.id = id;
}

public ChildEntity getChildEntity() {
return childEntity;
}

public void setChildEntity(ChildEntity childEntity) {
this.childEntity = childEntity;
if (childEntity != null) {
childEntity.setRootEntity(this);
}
}

public int getVersion() {
return version;
}

public void setVersion(int version) {
this.version = version;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
return false;
}
RootEntity event = (RootEntity) o;
return Objects.equals(id, event.id);
}

@Override
public int hashCode() {
return 0;
}
}

@Entity
@Table
public static class ChildEntity {

@Id
private UUID id;

@OneToOne(fetch = LAZY)
@MapsId
private RootEntity rootEntity;

@Version
private int version = -1;

public ChildEntity() {
}

public UUID getId() {
return id;
}

public void setId(UUID id) {
this.id = id;
}

public RootEntity getRootEntity() {
return rootEntity;
}

public void setRootEntity(RootEntity rootEntity) {
this.rootEntity = rootEntity;
}

public int getVersion() {
return version;
}

public void setVersion(int version) {
this.version = version;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
return false;
}
ChildEntity event = (ChildEntity) o;
return Objects.equals(id, event.id);
}

@Override
public int hashCode() {
return 0;
}
}

}