mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-13 14:44:48 +00:00
HHH-17776 - Add test and fix
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
85a2752c1d
commit
dcf91aadca
@ -67,13 +67,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||||||
|
|
||||||
public SqmQuerySpec(NodeBuilder nodeBuilder) {
|
public SqmQuerySpec(NodeBuilder nodeBuilder) {
|
||||||
super( nodeBuilder );
|
super( nodeBuilder );
|
||||||
|
// Enforce non-nullness of the fromClause
|
||||||
|
this.fromClause = new SqmFromClause();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmQuerySpec(SqmQuerySpec<T> original, SqmCopyContext context) {
|
public SqmQuerySpec(SqmQuerySpec<T> original, SqmCopyContext context) {
|
||||||
super( original, context );
|
super( original, context );
|
||||||
if ( original.fromClause != null ) {
|
|
||||||
this.fromClause = original.fromClause.copy( context );
|
this.fromClause = original.fromClause.copy( context );
|
||||||
}
|
|
||||||
if ( original.selectClause != null ) {
|
if ( original.selectClause != null ) {
|
||||||
this.selectClause = original.selectClause.copy( context );
|
this.selectClause = original.selectClause.copy( context );
|
||||||
}
|
}
|
||||||
@ -99,9 +99,7 @@ public SqmQuerySpec<T> copy(SqmCopyContext context) {
|
|||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
final SqmQuerySpec<T> querySpec = context.registerCopy( this, new SqmQuerySpec<>( nodeBuilder() ) );
|
final SqmQuerySpec<T> querySpec = context.registerCopy( this, new SqmQuerySpec<>( nodeBuilder() ) );
|
||||||
if ( fromClause != null ) {
|
|
||||||
querySpec.fromClause = fromClause.copy( context );
|
querySpec.fromClause = fromClause.copy( context );
|
||||||
}
|
|
||||||
if ( selectClause != null ) {
|
if ( selectClause != null ) {
|
||||||
querySpec.selectClause = selectClause.copy( context );
|
querySpec.selectClause = selectClause.copy( context );
|
||||||
}
|
}
|
||||||
@ -148,8 +146,11 @@ public SqmFromClause getFromClause() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setFromClause(SqmFromClause fromClause) {
|
public void setFromClause(SqmFromClause fromClause) {
|
||||||
|
// Enforce non-nullness of the fromClause
|
||||||
|
if ( fromClause != null ) {
|
||||||
this.fromClause = fromClause;
|
this.fromClause = fromClause;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean producesUniqueResults() {
|
public boolean producesUniqueResults() {
|
||||||
if ( fromClause.getRoots().size() != 1 ) {
|
if ( fromClause.getRoots().size() != 1 ) {
|
||||||
|
@ -9,35 +9,44 @@
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||||
|
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||||
|
import org.hibernate.query.criteria.JpaDerivedRoot;
|
||||||
|
import org.hibernate.query.criteria.JpaSubQuery;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
import org.hibernate.testing.orm.junit.Jpa;
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Tuple;
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
import jakarta.persistence.criteria.Root;
|
import jakarta.persistence.criteria.Root;
|
||||||
import jakarta.persistence.criteria.Subquery;
|
import jakarta.persistence.criteria.Subquery;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
@Jpa(
|
@Jpa(
|
||||||
annotatedClasses = {
|
annotatedClasses = {
|
||||||
RootInSubqueryWhereClauseTest.Person.class,
|
SubqueryTests.Person.class,
|
||||||
RootInSubqueryWhereClauseTest.Address.class
|
SubqueryTests.Address.class
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@TestForIssue(jiraKey = "HHH-15477")
|
public class SubqueryTests {
|
||||||
public class RootInSubqueryWhereClauseTest {
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeAll
|
||||||
public void setUp(EntityManagerFactoryScope scope){
|
public void setUp(EntityManagerFactoryScope scope){
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
entityManager -> {
|
entityManager -> {
|
||||||
@ -54,7 +63,8 @@ public void setUp(EntityManagerFactoryScope scope){
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSubquery(EntityManagerFactoryScope scope) {
|
@JiraKey(value = "HHH-15477")
|
||||||
|
public void testRootInSubqueryWhereClause(EntityManagerFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
entityManager -> {
|
entityManager -> {
|
||||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||||
@ -76,6 +86,50 @@ public void testSubquery(EntityManagerFactoryScope scope) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@JiraKey(value = "HHH-17776")
|
||||||
|
public void testNoFromClauseInSubquery(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
entityManager -> {
|
||||||
|
List<Person> entities = getEntities(entityManager);
|
||||||
|
assertEquals( 2, entities.size());
|
||||||
|
assertEquals("Jack", entities.get(0).getName());
|
||||||
|
assertEquals("Black", entities.get(0).getSurName());
|
||||||
|
assertEquals("John", entities.get(1).getName());
|
||||||
|
assertEquals("Doe", entities.get(1).getSurName());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Person> getEntities(EntityManager entityManager) {
|
||||||
|
|
||||||
|
HibernateCriteriaBuilder builder = entityManager.unwrap( Session.class ).getCriteriaBuilder();
|
||||||
|
JpaCriteriaQuery<Person> mainQuery = builder.createQuery( Person.class );
|
||||||
|
|
||||||
|
JpaSubQuery<Tuple> q1 = mainQuery.subquery(Tuple.class);
|
||||||
|
q1.multiselect(
|
||||||
|
builder.literal("John").alias("name"),
|
||||||
|
builder.literal("Doe").alias("surName")
|
||||||
|
);
|
||||||
|
|
||||||
|
JpaSubQuery<Tuple> q2 = mainQuery.subquery(Tuple.class);
|
||||||
|
q2.multiselect(
|
||||||
|
builder.literal("Jack").alias("name"),
|
||||||
|
builder.literal("Black").alias("surName")
|
||||||
|
);
|
||||||
|
|
||||||
|
JpaSubQuery<Tuple> unionAllSubQuery = builder.unionAll(q1, q2);
|
||||||
|
JpaDerivedRoot<Tuple> mainQueryRoot = mainQuery.from( unionAllSubQuery );
|
||||||
|
|
||||||
|
mainQuery.multiselect(
|
||||||
|
builder.trim(mainQueryRoot.get("name")).alias("name"),
|
||||||
|
builder.trim(mainQueryRoot.get("surName")).alias("surName")
|
||||||
|
);
|
||||||
|
mainQuery.orderBy( builder.asc(mainQueryRoot.get("name")) );
|
||||||
|
|
||||||
|
return entityManager.createQuery(mainQuery).getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
@Entity(name = "Person")
|
@Entity(name = "Person")
|
||||||
public static class Person {
|
public static class Person {
|
||||||
@Id
|
@Id
|
||||||
@ -83,6 +137,8 @@ public static class Person {
|
|||||||
|
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
String surName;
|
||||||
|
|
||||||
@OneToMany
|
@OneToMany
|
||||||
List<Address> addresses =new ArrayList<>();
|
List<Address> addresses =new ArrayList<>();
|
||||||
|
|
||||||
@ -90,8 +146,13 @@ public Person() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Person(Integer id, String name) {
|
public Person(Integer id, String name) {
|
||||||
|
this(id,name,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(Integer id, String name, String surName) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.surName = surName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAddress(Address address){
|
public void addAddress(Address address){
|
||||||
@ -107,6 +168,10 @@ public String getName() {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSurName() {
|
||||||
|
return surName;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Address> getAddresses() {
|
public List<Address> getAddresses() {
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user