HHH-15153 - @OneToOne does not support @EmbeddedId

This commit is contained in:
Nathan Xu 2022-05-11 21:17:53 -04:00 committed by Andrea Boriero
parent 7b2e93fa17
commit e87ad39dd6
4 changed files with 121 additions and 12 deletions

View File

@ -223,15 +223,7 @@ public class OneToOneSecondPass implements SecondPass {
// HHH-6813
// Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar
// Bar: @Id @OneToOne Foo foo
boolean referencesDerivedId = false;
try {
referencesDerivedId = otherSide.getIdentifier() instanceof Component
&& ( (Component) otherSide.getIdentifier() ).getProperty( mappedBy ) != null;
}
catch ( MappingException e ) {
// ignore
}
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
boolean referenceToPrimaryKey = ( mappedBy == null ) || otherSide.getIdentifier() instanceof Component && ! ( (Component) otherSide.getIdentifier() ).hasProperty( mappedBy ) ;
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
String propertyRef = value.getReferencedPropertyName();

View File

@ -378,7 +378,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
}
public Property getProperty(String propertyName) throws MappingException {
for ( Property prop : getProperties() ) {
for ( Property prop : properties ) {
if ( prop.getName().equals(propertyName) ) {
return prop;
}
@ -386,6 +386,15 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
throw new MappingException("component: " + componentClassName + " property not found: " + propertyName);
}
public boolean hasProperty(String propertyName) {
for ( Property prop : properties ) {
if ( prop.getName().equals(propertyName) ) {
return true;
}
}
return false;
}
public String getRoleName() {
return roleName;
}

View File

@ -5145,8 +5145,9 @@ public abstract class AbstractEntityPersister
}
else if ( identifierMapping instanceof NonAggregatedIdentifierMapping ) {
final EmbeddedAttributeMapping embeddedAttributeMapping = (EmbeddedAttributeMapping) findAttributeMapping( NavigableRole.IDENTIFIER_MAPPER_PROPERTY );
final AttributeMapping mapping = embeddedAttributeMapping.getMappedType()
.findAttributeMapping( basePropertyName );
final AttributeMapping mapping = embeddedAttributeMapping == null
? null
: embeddedAttributeMapping.getMappedType().findAttributeMapping( basePropertyName );
if ( mapping != null ) {
baseValue = mapping.getAttributeMetadataAccess()
.resolveAttributeMetadata( this )

View File

@ -0,0 +1,107 @@
package org.hibernate.orm.test.onetoone.embeddedid;
import java.io.Serializable;
import java.util.UUID;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.OneToOne;
/**
* @author Nathan Xu
*/
@Jpa(
annotatedClasses = {
OneToOneWithEmbeddedIdTest.Entity1.class,
OneToOneWithEmbeddedIdTest.Entity2.class,
OneToOneWithEmbeddedIdTest.ID1.class,
OneToOneWithEmbeddedIdTest.ID2.class
},
integrationSettings = @Setting(name = AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, value = "true")
)
@TestForIssue(jiraKey = "HHH-15153")
class OneToOneWithEmbeddedIdTest {
@Test
void testNoExceptionThrown(EntityManagerFactoryScope scope) {
ID1 id1 = new ID1();
ID2 id2 = new ID2();
Entity1 entity1 = new Entity1( id1 );
Entity2 entity2 = new Entity2( id2 );
entity2.entity1 = entity1;
scope.inTransaction( entityManager -> {
entityManager.persist( entity1 );
entityManager.persist( entity2 );
} );
entity1.value = 1;
entity2.value = 2;
// without fixing, the following will thrown exception
scope.inTransaction( entityManager -> {
entityManager.merge( entity1 );
entityManager.merge( entity2 );
} );
}
@Entity(name = "Entity1")
static class Entity1 {
@EmbeddedId
ID1 id;
@OneToOne(mappedBy = "entity1", cascade = CascadeType.ALL)
Entity2 entity2;
Integer value;
Entity1() {}
Entity1(ID1 id) {
this.id = id;
}
}
@Entity(name = "Entity2")
static class Entity2 {
@EmbeddedId
ID2 id;
@OneToOne(optional = false)
Entity1 entity1;
Integer value;
Entity2() {}
Entity2(ID2 id) {
this.id = id;
}
}
@Embeddable
static class ID1 implements Serializable {
String id = UUID.randomUUID().toString();
}
@Embeddable
static class ID2 implements Serializable {
String id = UUID.randomUUID().toString();
}
}