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 @@ -407,7 +407,9 @@ private static boolean supportsFunctionalDependency(Dialect dialect, EntityMappi
final FunctionalDependencyAnalysisSupport analysisSupport = dialect.getFunctionalDependencyAnalysisSupport();
if ( analysisSupport.supportsAnalysis() ) {
if ( entityMappingType.getSqmMultiTableMutationStrategy() == null ) {
return true;
// A subquery may be used to render a single-table inheritance subtype, in which case
// we cannot use functional dependency analysis unless the dialect supports table groups
return analysisSupport.supportsTableGroups() || entityMappingType.getSuperMappingType() == null;
}
else {
return analysisSupport.supportsTableGroups() && ( analysisSupport.supportsConstants() ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.inheritance;

import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Tuple;
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.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@DomainModel( annotatedClasses = {
InheritanceToOneSubtypeJoinGroupByTest.Base.class,
InheritanceToOneSubtypeJoinGroupByTest.EntityA.class,
InheritanceToOneSubtypeJoinGroupByTest.EntityB.class,
InheritanceToOneSubtypeJoinGroupByTest.WhitelistEntry.class,
} )
@SessionFactory
public class InheritanceToOneSubtypeJoinGroupByTest {
@Test
void testGroupByA(SessionFactoryScope scope) {
scope.inSession( session -> {
final EntityA result = session.createQuery(
"SELECT a FROM WhitelistEntry we JOIN we.primaryKey.a a group by a",
EntityA.class
).getSingleResult();
assertThat( result.getAName() ).isEqualTo( "a" );
} );
}

@Test
void testGroupByB(SessionFactoryScope scope) {
scope.inSession( session -> {
final Tuple result = session.createQuery(
"SELECT b.id, b.bName FROM WhitelistEntry we JOIN we.primaryKey.b b group by b",
Tuple.class
).getSingleResult();
assertThat( result.get( 1, String.class ) ).isEqualTo( "b" );
} );
}

@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final EntityA a = new EntityA();
a.setAName( "a" );
final EntityB b = new EntityB();
b.setBName( "b" );
final WhitelistEntry whitelistEntry = new WhitelistEntry();
whitelistEntry.setName( "whitelistEntry" );
final WhitelistEntryPK primaryKey = new WhitelistEntryPK();
primaryKey.setA( a );
primaryKey.setB( b );
whitelistEntry.setPrimaryKey( primaryKey );
session.persist( a );
session.persist( b );
session.persist( whitelistEntry );
} );
}

@AfterAll
public void tearDown(SessionFactoryScope scope) {
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
}

@Entity(name = "Base")
@Inheritance
public static class Base {
@Id
@GeneratedValue
private Long id;
}


@Entity(name = "EntityA")
public static class EntityA extends Base {
private String aName;

public String getAName() {
return aName;
}

public void setAName(String name) {
this.aName = name;
}
}

@Entity(name = "EntityB")
public static class EntityB extends Base {
private String bName;

public String getBName() {
return bName;
}

public void setBName(String name) {
this.bName = name;
}
}

@Embeddable
public static class WhitelistEntryPK {
@ManyToOne
private EntityB b;

@ManyToOne
private EntityA a;

public WhitelistEntryPK() {
}

public EntityB getB() {
return b;
}

public void setB(EntityB b) {
this.b = b;
}

public EntityA getA() {
return a;
}

public void setA(EntityA a) {
this.a = a;
}
}

@Entity(name = "WhitelistEntry")
public static class WhitelistEntry {
@EmbeddedId
private WhitelistEntryPK primaryKey;

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public WhitelistEntryPK getPrimaryKey() {
return primaryKey;
}

public void setPrimaryKey(WhitelistEntryPK primaryKey) {
this.primaryKey = primaryKey;
}
}
}
Loading