Fix joined inheriatance with concrete root
This commit is contained in:
parent
0f2e5dca8c
commit
42213c860a
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="hibernate-core-hibernate-core" />
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false" />
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/home/aboriero/hibernate/wip_60_steve/hibernate-core/gradlew" />
|
||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_REFRESH_RECURSIVE" value="false" />
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/hibernate-core-hibernate-core/src/test/bundles" type="2"/> <item path="/hibernate-core-hibernate-core/src/test/resources" type="2"/> </resources>}" />
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false" />
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/hibernate-core-hibernate-core/src/test/bundles" type="2"/> <item path="/hibernate-core-hibernate-core/src/test/resources" type="2"/> </resources>}" />
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto," />
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="hibernate-core:processTestResources --no-daemon" />
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true" />
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="/home/aboriero/hibernate/wip_60_steve/hibernate-core" />
|
||||
</launchConfiguration><!-- AUTO-GENERATED FILE. DO NOT MODIFY. This is generated by gradle eclipse task -->
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="hibernate-core-hibernate-core" />
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4" />
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=hibernate-core-hibernate-core" />
|
||||
<stringAttribute key="org.eclipse.jdt.junit.EXCLUDE_TAGS" value="" />
|
||||
<booleanAttribute key="org.eclipse.jdt.junit.HAS_EXCLUDE_TAGS" value="false" />
|
||||
<booleanAttribute key="org.eclipse.jdt.junit.HAS_INCLUDE_TAGS" value="true" />
|
||||
<stringAttribute key="org.eclipse.jdt.junit.INCLUDE_TAGS" value="RunnableIdeTest" />
|
||||
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false" />
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value="" />
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit5" />
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="" />
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="hibernate-core" />
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea" />
|
||||
</launchConfiguration><!-- AUTO-GENERATED FILE. DO NOT MODIFY. This is generated by gradle eclipse task -->
|
|
@ -8,12 +8,15 @@ package org.hibernate.persister.entity;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -43,10 +46,14 @@ import org.hibernate.mapping.Selectable;
|
|||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.JoinedSubclassDiscriminatorMappingImpl;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.InFragment;
|
||||
import org.hibernate.sql.Insert;
|
||||
|
@ -55,6 +62,7 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.JoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
@ -1169,6 +1177,42 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValues(Object object, Object[] values) {
|
||||
if ( accessOptimizer != null ) {
|
||||
accessOptimizer.setPropertyValues( object, values );
|
||||
}
|
||||
else {
|
||||
if ( hasSubclasses() ) {
|
||||
visitAttributeMappings(
|
||||
attribute -> {
|
||||
final int stateArrayPosition = ( (StateArrayContributorMapping) attribute ).getStateArrayPosition();
|
||||
final Object value = values[stateArrayPosition];
|
||||
if ( value != UNFETCHED_PROPERTY ) {
|
||||
final Setter setter = attribute.getPropertyAccess().getSetter();
|
||||
setter.set( object, value, getFactory() );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
visitFetchables(
|
||||
fetchable -> {
|
||||
final AttributeMapping attribute = (AttributeMapping) fetchable;
|
||||
final int stateArrayPosition = ( (StateArrayContributorMapping) attribute ).getStateArrayPosition();
|
||||
final Object value = values[stateArrayPosition];
|
||||
if ( value != UNFETCHED_PROPERTY ) {
|
||||
final Setter setter = attribute.getPropertyAccess().getSetter();
|
||||
setter.set( object, value, getFactory() );
|
||||
}
|
||||
|
||||
},
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
NavigablePath navigablePath,
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
|
||||
|
||||
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.Tag;
|
||||
import org.junit.jupiter.api.Tags;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
JoinedInheritanceWithConcreteRootTest.Customer.class,
|
||||
JoinedInheritanceWithConcreteRootTest.DomesticCustomer.class,
|
||||
JoinedInheritanceWithConcreteRootTest.ForeignCustomer.class
|
||||
}
|
||||
)
|
||||
@ServiceRegistry
|
||||
@SessionFactory
|
||||
@Tags({
|
||||
@Tag("RunnableIdeTest"),
|
||||
})
|
||||
public class JoinedInheritanceWithConcreteRootTest {
|
||||
@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 instanceof JoinedSubclassEntityPersister;
|
||||
|
||||
assert customerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert !customerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert !customerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
|
||||
assert domesticCustomerDescriptor instanceof JoinedSubclassEntityPersister;
|
||||
|
||||
assert domesticCustomerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert domesticCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert !domesticCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
|
||||
assert foreignCustomerDescriptor instanceof JoinedSubclassEntityPersister;
|
||||
|
||||
assert foreignCustomerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert !foreignCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert foreignCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rootQueryExecutionTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
{
|
||||
// [name, taxId, vat]
|
||||
final List<Customer> results = session.createQuery(
|
||||
"select c from Customer c",
|
||||
Customer.class
|
||||
).list();
|
||||
|
||||
assertThat( results.size(), is( 3 ) );
|
||||
boolean foundDomesticCustomer = false;
|
||||
boolean foundForeignCustomer = false;
|
||||
boolean foundCustomer = false;
|
||||
for ( Customer result : results ) {
|
||||
if ( result.getId() == 1 ) {
|
||||
assertThat( result, instanceOf( DomesticCustomer.class ) );
|
||||
final DomesticCustomer customer = (DomesticCustomer) result;
|
||||
assertThat( customer.getName(), is( "domestic" ) );
|
||||
assertThat( ( customer ).getTaxId(), is( "123" ) );
|
||||
foundDomesticCustomer = true;
|
||||
}
|
||||
else if ( result.getId() == 2 ) {
|
||||
final ForeignCustomer customer = (ForeignCustomer) result;
|
||||
assertThat( customer.getName(), is( "foreign" ) );
|
||||
assertThat( ( customer ).getVat(), is( "987" ) );
|
||||
foundForeignCustomer = true;
|
||||
}
|
||||
else {
|
||||
assertThat( result.getId(), is( 3 ) );
|
||||
final Customer customer = result;
|
||||
assertThat( customer.getName(), is( "customer" ) );
|
||||
foundCustomer = true;
|
||||
}
|
||||
}
|
||||
assertTrue( foundDomesticCustomer );
|
||||
assertTrue( foundForeignCustomer );
|
||||
assertTrue( foundCustomer );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@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" ) );
|
||||
session.persist( new Customer( 3, "customer" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanupTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.doWork(
|
||||
work -> {
|
||||
Statement statement = work.createStatement();
|
||||
try {
|
||||
statement.execute( "delete from DomesticCustomer" );
|
||||
statement.execute( "delete from ForeignCustomer" );
|
||||
statement.execute( "delete from Customer" );
|
||||
}
|
||||
finally {
|
||||
statement.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Customer")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Table(name = "Customer")
|
||||
public static class Customer {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public Customer() {
|
||||
}
|
||||
|
||||
public Customer(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "DomesticCustomer")
|
||||
@Table(name = "DomesticCustomer")
|
||||
public static class DomesticCustomer extends Customer {
|
||||
private String taxId;
|
||||
|
||||
public DomesticCustomer() {
|
||||
}
|
||||
|
||||
public DomesticCustomer(Integer id, String name, String taxId) {
|
||||
super( id, name );
|
||||
this.taxId = taxId;
|
||||
}
|
||||
|
||||
public String getTaxId() {
|
||||
return taxId;
|
||||
}
|
||||
|
||||
public void setTaxId(String taxId) {
|
||||
this.taxId = taxId;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "ForeignCustomer")
|
||||
@Table(name = "ForeignCustomer")
|
||||
public static class ForeignCustomer extends Customer {
|
||||
private String vat;
|
||||
|
||||
public ForeignCustomer() {
|
||||
}
|
||||
|
||||
public ForeignCustomer(Integer id, String name, String vat) {
|
||||
super( id, name );
|
||||
this.vat = vat;
|
||||
}
|
||||
|
||||
public String getVat() {
|
||||
return vat;
|
||||
}
|
||||
|
||||
public void setVat(String vat) {
|
||||
this.vat = vat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue