Fix throw exception when an Entity has an EmbeddedId being also an IdClass of another Entity

This commit is contained in:
Andrea Boriero 2021-11-01 21:59:12 +01:00 committed by Christian Beikov
parent 9d08be53a6
commit eae9a39b14
7 changed files with 83 additions and 58 deletions

View File

@ -687,7 +687,7 @@ public class MetadataContext {
domainType = (EmbeddableDomainType<J>) embeddableDomainType; domainType = (EmbeddableDomainType<J>) embeddableDomainType;
break; break;
} }
else if ( cachedComponent.getComponentClass().equals( component.getComponentClass() ) ) { else if ( cachedComponent.getComponentClass().equals( component.getComponentClass() ) || cachedComponent.isEmbedded() != component.isEmbedded() ) {
final int cachedComponentPropertySpan = cachedComponent.getPropertySpan(); final int cachedComponentPropertySpan = cachedComponent.getPropertySpan();
if ( cachedComponentPropertySpan != component.getPropertySpan() ) { if ( cachedComponentPropertySpan != component.getPropertySpan() ) {
throw new MappingException( throw new MappingException(

View File

@ -4698,8 +4698,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final Expression lhsExpression = comparisonPredicate.getLeftHandExpression(); final Expression lhsExpression = comparisonPredicate.getLeftHandExpression();
if ( lhsExpression instanceof QueryGroup ) { if ( lhsExpression instanceof QueryGroup ) {
final QueryGroup subquery = (QueryGroup) lhsExpression;
if ( rhsTuple.getExpressions().size() == 1 ) { if ( rhsTuple.getExpressions().size() == 1 ) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
renderComparison( renderComparison(
@ -4719,7 +4717,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
emulateSubQueryRelationalRestrictionPredicate( emulateSubQueryRelationalRestrictionPredicate(
comparisonPredicate, comparisonPredicate,
false, false,
subquery, (QueryGroup) lhsExpression,
rhsTuple, rhsTuple,
this::renderSelectTupleComparison, this::renderSelectTupleComparison,
// Since we switch the order of operands, we have to invert the operator // Since we switch the order of operands, we have to invert the operator

View File

@ -0,0 +1,70 @@
/*
* 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.annotations.derivedidentities.e5.b;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.orm.test.util.SchemaUtil;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Emmanuel Bernard
*/
@DomainModel(
annotatedClasses = {
MedicalHistory.class,
Person.class
}
)
@SessionFactory
public class DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest {
@Test
public void testOneToOneExplicitJoinColumn(SessionFactoryScope scope) {
final MetadataImplementor metadata = scope.getMetadataImplementor();
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata ) );
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata ) );
assertTrue( !SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata ) );
Person e = new Person();
final String firstName = "Emmanuel";
final String lastName = "Bernard";
e.firstName = firstName;
e.lastName = lastName;
scope.inTransaction(
session -> {
session.persist( e );
MedicalHistory d = new MedicalHistory();
d.patient = e;
session.persist( d );
session.flush();
session.clear();
d = session.get( MedicalHistory.class, d.id );
assertEquals( d.id.firstName, d.patient.firstName );
}
);
scope.inTransaction(
session -> {
PersonId pId = new PersonId( firstName, lastName );
MedicalHistory d2 = session.get( MedicalHistory.class, pId );
Person p2 = session.get( Person.class, pId );
assertEquals( pId.firstName, d2.patient.firstName );
assertEquals( pId.firstName, p2.firstName );
session.delete( d2 );
session.delete( p2 );
}
);
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.derivedidentities.e5.b; package org.hibernate.orm.test.annotations.derivedidentities.e5.b;
import jakarta.persistence.EmbeddedId; import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.derivedidentities.e5.b; package org.hibernate.orm.test.annotations.derivedidentities.e5.b;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.IdClass; import jakarta.persistence.IdClass;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.derivedidentities.e5.b; package org.hibernate.orm.test.annotations.derivedidentities.e5.b;
import java.io.Serializable; import java.io.Serializable;
/** /**
@ -13,4 +13,12 @@ import java.io.Serializable;
public class PersonId implements Serializable { public class PersonId implements Serializable {
String firstName; String firstName;
String lastName; String lastName;
public PersonId() {
}
public PersonId(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
} }

View File

@ -1,51 +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>.
*/
package org.hibernate.test.annotations.derivedidentities.e5.b;
import org.hibernate.Session;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.orm.test.util.SchemaUtil;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Emmanuel Bernard
*/
public class DerivedIdentityIdClassParentSameIdTypeEmbeddedIdDepTest extends BaseNonConfigCoreFunctionalTestCase {
@Test
public void testOneToOneExplicitJoinColumn() throws Exception {
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", metadata() ) );
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", metadata() ) );
assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", metadata() ) );
Person e = new Person();
e.firstName = "Emmanuel";
e.lastName = "Bernard";
Session s = openSession( );
s.getTransaction().begin();
s.persist( e );
MedicalHistory d = new MedicalHistory();
d.patient = e;
s.persist( d );
s.flush();
s.clear();
d = (MedicalHistory) s.get( MedicalHistory.class, d.id );
assertEquals( d.id.firstName, d.patient.firstName );
s.getTransaction().rollback();
s.close();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
MedicalHistory.class,
Person.class
};
}
}