HHH-13777 UnsupportedOperationException is thrown for MappedSuperclass if the id is declared on subclasses

This commit is contained in:
Andrea Boriero 2019-12-11 11:31:43 +00:00
parent 3eed218135
commit 1580613f8a
3 changed files with 214 additions and 2 deletions

View File

@ -20,7 +20,6 @@ import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger;
@ -389,7 +388,14 @@ public abstract class AbstractIdentifiableType<J>
throw new NotYetImplementedFor6Exception( getClass() );
}
else {
if ( isIdMappingRequired() ) {
throw new UnsupportedOperationException( "Could not build SqmPathSource for entity identifier : " + getTypeName() );
}
return null;
}
}
protected boolean isIdMappingRequired() {
return true;
}
}

View File

@ -54,4 +54,9 @@ public class MappedSuperclassTypeImpl<X> extends AbstractIdentifiableType<X> imp
public <S extends X> SubGraphImplementor<S> makeSubGraph(Class<S> subType) {
throw new NotYetImplementedException( );
}
@Override
protected boolean isIdMappingRequired() {
return false;
}
}

View File

@ -0,0 +1,201 @@
/*
* 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.metamodel.mapping.inheritance;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
MappedSuperclassWithIdOnSubclassesTest.DomesticCustomer.class,
MappedSuperclassWithIdOnSubclassesTest.ForeignCustomer.class
}
)
@ServiceRegistry
@SessionFactory
public class MappedSuperclassWithIdOnSubclassesTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister customerDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( Customer.class );
final EntityPersister domesticCustomerDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( DomesticCustomer.class );
final EntityPersister foreignCustomerDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( ForeignCustomer.class );
assert customerDescriptor == null;
assert domesticCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
assert !domesticCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
assert !foreignCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
assert foreignCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
}
@Test
public void subclassQueryExecutionTest(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
{
final DomesticCustomer result = session.createQuery(
"select c from DomesticCustomer c",
DomesticCustomer.class
).uniqueResult();
assertThat( result, notNullValue() );
assertThat( result.getId(), is( 1 ) );
assertThat( result.getName(), is( "domestic" ) );
assertThat( result.getTaxId(), is( "123" ) );
}
{
final ForeignCustomer result = session.createQuery(
"select c from ForeignCustomer c",
ForeignCustomer.class
).uniqueResult();
assertThat( result, notNullValue() );
assertThat( result.getId(), is( 2 ) );
assertThat( result.getName(), is( "foreign" ) );
assertThat( result.getVat(), is( "987" ) );
}
}
);
}
@BeforeEach
public void createTestData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.persist( new DomesticCustomer( 1, "domestic", "123" ) );
session.persist( new ForeignCustomer( 2, "foreign", "987" ) );
}
);
}
@AfterEach
public void cleanupTestData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "from DomesticCustomer", DomesticCustomer.class )
.list()
.forEach( cust -> session.delete( cust ) );
session.createQuery( "from ForeignCustomer", ForeignCustomer.class )
.list()
.forEach( cust -> session.delete( cust ) );
}
);
}
@MappedSuperclass
public static abstract class Customer {
private String name;
public Customer() {
}
public Customer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "DomesticCustomer")
public static class DomesticCustomer extends Customer {
private Integer id;
private String taxId;
public DomesticCustomer() {
}
public DomesticCustomer(Integer id, String name, String taxId) {
super( name );
this.id = id;
this.taxId = taxId;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTaxId() {
return taxId;
}
public void setTaxId(String taxId) {
this.taxId = taxId;
}
}
@Entity(name = "ForeignCustomer")
public static class ForeignCustomer extends Customer {
private Integer id;
private String vat;
public ForeignCustomer() {
}
public ForeignCustomer(Integer id, String name, String vat) {
super( name );
this.id = id;
this.vat = vat;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getVat() {
return vat;
}
public void setVat(String vat) {
this.vat = vat;
}
}
}