Fix native named query max results

This commit is contained in:
Andrea Boriero 2022-02-08 18:51:52 +01:00 committed by Andrea Boriero
parent 74e1e6caad
commit 07f3d6727f
6 changed files with 146 additions and 10 deletions

View File

@ -27,6 +27,8 @@ public class NamedNativeQueryDefinitionImpl extends AbstractNamedQueryDefinition
private final String resultSetMappingName;
private final String resultSetMappingClassName;
private final Set<String> querySpaces;
private Integer firstResult;
private Integer maxResults;
public NamedNativeQueryDefinitionImpl(
String name,
@ -42,6 +44,8 @@ public class NamedNativeQueryDefinitionImpl extends AbstractNamedQueryDefinition
Integer timeout,
Integer fetchSize,
String comment,
Integer firstResult,
Integer maxResults,
Map<String,Object> hints) {
super(
name,
@ -60,6 +64,8 @@ public class NamedNativeQueryDefinitionImpl extends AbstractNamedQueryDefinition
this.resultSetMappingName = resultSetMappingName;
this.resultSetMappingClassName = resultSetMappingClassName;
this.querySpaces = querySpaces;
this.firstResult = firstResult;
this.maxResults = maxResults;
}
@Override
@ -97,6 +103,8 @@ public class NamedNativeQueryDefinitionImpl extends AbstractNamedQueryDefinition
getTimeout(),
getFetchSize(),
getComment(),
firstResult,
maxResults,
getHints()
);
}

View File

@ -28,6 +28,8 @@ public class NamedNativeQueryDefinitionBuilder extends AbstractNamedQueryBuilder
private Set<String> querySpaces;
private Map<String, String> parameterTypes;
private Integer firstResult;
private Integer maxResults;
public NamedNativeQueryDefinitionBuilder(String name) {
super( name );
@ -38,6 +40,16 @@ public class NamedNativeQueryDefinitionBuilder extends AbstractNamedQueryBuilder
return getThis();
}
public NamedNativeQueryDefinitionBuilder setFirstResult(Integer firstResult) {
this.firstResult = firstResult;
return getThis();
}
public NamedNativeQueryDefinitionBuilder setMaxResults(Integer maxResults) {
this.maxResults = maxResults;
return getThis();
}
public NamedNativeQueryDefinition build() {
return new NamedNativeQueryDefinitionImpl(
getName(),
@ -53,6 +65,8 @@ public class NamedNativeQueryDefinitionBuilder extends AbstractNamedQueryBuilder
getTimeout(),
getFetchSize(),
getComment(),
firstResult,
maxResults,
getHints()
);
}

View File

@ -14,7 +14,6 @@ import org.hibernate.FlushMode;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.named.AbstractNamedQueryMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
@ -32,6 +31,10 @@ public class NamedNativeQueryMementoImpl extends AbstractNamedQueryMemento imple
private final Set<String> querySpaces;
private final Integer firstResult;
private final Integer maxResults;
public NamedNativeQueryMementoImpl(
String name,
String sqlString,
@ -46,6 +49,8 @@ public class NamedNativeQueryMementoImpl extends AbstractNamedQueryMemento imple
Integer timeout,
Integer fetchSize,
String comment,
Integer firstResult,
Integer maxResults,
Map<String,Object> hints) {
super(
name,
@ -65,6 +70,8 @@ public class NamedNativeQueryMementoImpl extends AbstractNamedQueryMemento imple
: resultSetMappingName;
this.resultSetMappingClass = resultSetMappingClass;
this.querySpaces = querySpaces;
this.firstResult = firstResult;
this.maxResults = maxResults;
}
public String getResultSetMappingName() {
@ -94,6 +101,16 @@ public class NamedNativeQueryMementoImpl extends AbstractNamedQueryMemento imple
return resultSetMappingClass;
}
@Override
public Integer getFirstResult() {
return firstResult;
}
@Override
public Integer getMaxResults() {
return maxResults;
}
@Override
public NamedNativeQueryMemento makeCopy(String name) {
return new NamedNativeQueryMementoImpl(
@ -110,6 +127,8 @@ public class NamedNativeQueryMementoImpl extends AbstractNamedQueryMemento imple
getTimeout(),
getFetchSize(),
getComment(),
getFirstResult(),
getMaxResults(),
getHints()
);
}

View File

@ -360,6 +360,13 @@ public class NativeQueryImpl<R>
protected void applyOptions(NamedNativeQueryMemento memento) {
super.applyOptions( memento );
if ( memento.getMaxResults() != null ) {
setMaxResults( memento.getMaxResults() );
}
if ( memento.getFirstResult() != null ) {
setFirstResult( memento.getFirstResult() );
}
final Set<String> copy = CollectionHelper.makeCopy( memento.getQuerySpaces() );
if ( copy != null ) {
this.querySpaces = copy;
@ -457,8 +464,9 @@ public class NativeQueryImpl<R>
getTimeout(),
getFetchSize(),
getComment(),
getFirstResult(),
getMaxResults(),
getHints()
);
}

View File

@ -47,6 +47,10 @@ public interface NamedNativeQueryMemento extends NamedQueryMemento {
*/
Class<?> getResultMappingClass();
Integer getFirstResult();
Integer getMaxResults();
/**
* Convert the memento into an untyped executable query
*/
@ -142,6 +146,8 @@ public interface NamedNativeQueryMemento extends NamedQueryMemento {
timeout,
fetchSize,
comment,
firstResult,
maxResults,
hints
);
}

View File

@ -9,42 +9,55 @@ package org.hibernate.orm.test.jpa.compliance;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Id;
import jakarta.persistence.Query;
import jakarta.persistence.Table;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Jpa(
annotatedClasses = NamedQueryTest.Person.class
annotatedClasses = NamedQueryTest.Person.class,
properties = @Setting(name = AvailableSettings.JPA_CRITERIA_COPY_COMPLIANCE, value = "true")
)
public class NamedQueryTest {
@BeforeEach
public void setup(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
Person person1 = new Person( 1, "Andrea" );
Person person2 = new Person( 2, "Alberto" );
entityManager.persist( person1 );
entityManager.persist( person2 );
entityManager.persist( new Person( 1, "Andrea" ) );
entityManager.persist( new Person( 2, "Alberto" ) );
}
);
}
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager ->
entityManager.createQuery( "delete from Person" ).executeUpdate()
);
}
@Test
public void testNameQueryCreationFromCritera(EntityManagerFactoryScope scope) {
public void testNameQueryCreationFromCriteria(EntityManagerFactoryScope scope) {
final EntityManagerFactory entityManagerFactory = scope.getEntityManagerFactory();
@ -68,6 +81,74 @@ public class NamedQueryTest {
}
@Test
public void testNativeWithMaxResults(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final Query nativeQuery = entityManager.createNativeQuery(
"Select p.id from PERSON_TABLE p" );
nativeQuery.setMaxResults( 1 );
scope.getEntityManagerFactory().addNamedQuery( "native", nativeQuery );
final Query namedQuery = entityManager.createNamedQuery( "native" );
assertEquals( 1, namedQuery.getMaxResults() );
namedQuery.setMaxResults( 2 );
assertEquals( 2, namedQuery.getMaxResults() );
final List<Integer> ids = namedQuery.getResultList();
assertEquals( 2, ids.size() );
assertThat( ids, hasItems( 1, 2 ) );
} );
}
@Test
public void testCriteriaWithMaxResults(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Integer> criteriaQuery = criteriaBuilder.createQuery( Integer.class );
final Root<Person> person = criteriaQuery.from( Person.class );
criteriaQuery.select( person.get( "id" ) );
criteriaQuery.orderBy( criteriaBuilder.asc( person.get( "id" ) ) );
final TypedQuery<Integer> typedQuery = entityManager.createQuery( criteriaQuery );
typedQuery.setMaxResults( 1 );
scope.getEntityManagerFactory().addNamedQuery( "criteria", typedQuery );
final Query namedQuery = entityManager.createNamedQuery( "criteria" );
assertEquals( 1, namedQuery.getMaxResults() );
namedQuery.setMaxResults( 2 );
assertEquals( 2, namedQuery.getMaxResults() );
final List<Integer> ids = namedQuery.getResultList();
assertEquals( 2, ids.size() );
assertThat( ids, hasItems( 1, 2 ) );
} );
}
@Test
public void testHqlWithMaxResults(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final Query query = entityManager.createQuery( "Select p.id from Person p" );
query.setMaxResults( 1 );
scope.getEntityManagerFactory().addNamedQuery( "query", query );
final Query namedQuery = entityManager.createNamedQuery( "query" );
assertEquals( 1, namedQuery.getMaxResults() );
namedQuery.setMaxResults( 2 );
assertEquals( 2, namedQuery.getMaxResults() );
final List<Integer> ids = namedQuery.getResultList();
assertEquals( 2, ids.size() );
assertThat( ids, hasItems( 1, 2 ) );
} );
}
@Entity(name = "Person")
@Table(name = "PERSON_TABLE")
public static class Person {