add Query.getSingleResultOrNull()
this is quite similar to the existing uniqueResult() method, but its name is much clearer, and it throws the JPA exception
This commit is contained in:
parent
d7e5d55278
commit
c8a4546331
|
@ -1024,6 +1024,24 @@ public class ProcedureCallImpl<R>
|
|||
return resultList.get( 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public R getSingleResultOrNull() {
|
||||
final List<R> resultList = getResultList();
|
||||
if ( resultList == null || resultList.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
else if ( resultList.size() > 1 ) {
|
||||
throw new NonUniqueResultException(
|
||||
String.format(
|
||||
"Call to stored procedure [%s] returned multiple results",
|
||||
getProcedureName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return resultList.get( 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> cls) {
|
||||
|
|
|
@ -161,7 +161,7 @@ public interface Query<R> extends SelectionQuery<R>, MutationQuery, TypedQuery<R
|
|||
* Execute the query and return the single result of the query, or
|
||||
* {@code null} if the query returns no results.
|
||||
*
|
||||
* @return the single result or {@code null}
|
||||
* @return the single result or {@code null} if there is no result to return
|
||||
*
|
||||
* @throws NonUniqueResultException if there is more than one matching result
|
||||
*/
|
||||
|
|
|
@ -134,6 +134,16 @@ public interface SelectionQuery<R> extends CommonQueryContract {
|
|||
*/
|
||||
R getSingleResult();
|
||||
|
||||
/**
|
||||
* Execute the query and return the single result of the query,
|
||||
* or {@code null} if the query returns no results.
|
||||
*
|
||||
* @return the single result or {@code null} if there is no result to return
|
||||
*
|
||||
* @throws jakarta.persistence.NonUniqueResultException if there is more than one matching result
|
||||
*/
|
||||
R getSingleResultOrNull();
|
||||
|
||||
/**
|
||||
* Execute the query and return the single result of the query,
|
||||
* as an {@link Optional}.
|
||||
|
|
|
@ -653,7 +653,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
|
|||
return (Set) getParameterMetadata().getRegistrations();
|
||||
}
|
||||
|
||||
public QueryParameter<?> getParameter(String name) {
|
||||
public QueryParameterImplementor<?> getParameter(String name) {
|
||||
getSession().checkOpen( false );
|
||||
|
||||
try {
|
||||
|
@ -665,12 +665,12 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> QueryParameter<T> getParameter(String name, Class<T> type) {
|
||||
public <T> QueryParameterImplementor<T> getParameter(String name, Class<T> type) {
|
||||
getSession().checkOpen( false );
|
||||
|
||||
try {
|
||||
//noinspection rawtypes
|
||||
final QueryParameter parameter = getParameterMetadata().getQueryParameter( name );
|
||||
final QueryParameterImplementor parameter = getParameterMetadata().getQueryParameter( name );
|
||||
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
"The type [" + parameter.getParameterType().getName() +
|
||||
|
@ -685,7 +685,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
|
|||
}
|
||||
}
|
||||
|
||||
public QueryParameter<?> getParameter(int position) {
|
||||
public QueryParameterImplementor<?> getParameter(int position) {
|
||||
getSession().checkOpen( false );
|
||||
|
||||
try {
|
||||
|
@ -697,11 +697,11 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
|
|||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked", "rawtypes"} )
|
||||
public <T> QueryParameter<T> getParameter(int position, Class<T> type) {
|
||||
public <T> QueryParameterImplementor<T> getParameter(int position, Class<T> type) {
|
||||
getSession().checkOpen( false );
|
||||
|
||||
try {
|
||||
final QueryParameter parameter = getParameterMetadata().getQueryParameter( position );
|
||||
final QueryParameterImplementor parameter = getParameterMetadata().getQueryParameter( position );
|
||||
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
"The type [" + parameter.getParameterType().getName() +
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,11 @@ import java.util.Spliterator;
|
|||
import java.util.Spliterators;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jakarta.persistence.FlushModeType;
|
||||
import jakarta.persistence.LockModeType;
|
||||
import jakarta.persistence.NoResultException;
|
||||
import jakarta.persistence.Parameter;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
|
@ -39,12 +44,6 @@ import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
|||
import org.hibernate.sql.exec.internal.CallbackImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
|
||||
import jakarta.persistence.FlushModeType;
|
||||
import jakarta.persistence.LockModeType;
|
||||
import jakarta.persistence.NoResultException;
|
||||
import jakarta.persistence.Parameter;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
|
@ -152,7 +151,7 @@ public abstract class AbstractSelectionQuery<R>
|
|||
getSession().setHibernateFlushMode( effectiveFlushMode );
|
||||
}
|
||||
|
||||
final CacheMode effectiveCacheMode = ( (SelectionQuery) this ).getCacheMode();
|
||||
final CacheMode effectiveCacheMode = getCacheMode();
|
||||
if ( effectiveCacheMode != null ) {
|
||||
sessionCacheMode = getSession().getCacheMode();
|
||||
getSession().setCacheMode( effectiveCacheMode );
|
||||
|
@ -244,6 +243,16 @@ public abstract class AbstractSelectionQuery<R>
|
|||
return Optional.ofNullable( uniqueResult() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public R getSingleResultOrNull() {
|
||||
try {
|
||||
return uniqueElement( list() );
|
||||
}
|
||||
catch ( HibernateException e ) {
|
||||
throw getSession().getExceptionConverter().convert( e, getLockOptions() );
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean hasLimit(SqmSelectStatement<?> sqm, MutableQueryOptions queryOptions) {
|
||||
return queryOptions.hasLimit() || sqm.getFetch() != null || sqm.getOffset() != null;
|
||||
}
|
||||
|
|
|
@ -36,70 +36,70 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
@RequiresDialect( H2Dialect.class )
|
||||
@JiraKey("https://hibernate.atlassian.net/browse/HHH-11447")
|
||||
public class ProcedureParameterTests {
|
||||
|
||||
@Test
|
||||
public void testRegisteredParameter(EntityManagerFactoryScope scope) {
|
||||
// locate takes 2 parameters with an optional 3rd. Here, we will call it
|
||||
// registering and binding all 3 parameters
|
||||
scope.inTransaction( (em) -> {
|
||||
final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// search-tring
|
||||
query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// source-string
|
||||
query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
// start-position
|
||||
query.registerStoredProcedureParameter( 3, Integer.class, ParameterMode.IN );
|
||||
|
||||
query.setParameter( 1, "." );
|
||||
query.setParameter( 2, "org.hibernate.query" );
|
||||
query.setParameter( 3, 5 );
|
||||
|
||||
final Object singleResult = query.getSingleResult();
|
||||
assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
assertThat( singleResult ).isEqualTo( 14 );
|
||||
} );
|
||||
|
||||
// explicit start-position baseline for no-arg
|
||||
|
||||
scope.inTransaction( (em) -> {
|
||||
final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// search-string
|
||||
query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// source-string
|
||||
query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
// start-position
|
||||
query.registerStoredProcedureParameter( 3, Integer.class, ParameterMode.IN );
|
||||
|
||||
query.setParameter( 1, "." );
|
||||
query.setParameter( 2, "org.hibernate.query" );
|
||||
query.setParameter( 3, 0 );
|
||||
|
||||
final Object singleResult = query.getSingleResult();
|
||||
assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
assertThat( singleResult ).isEqualTo( 4 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnRegisteredParameter(EntityManagerFactoryScope scope) {
|
||||
// next, skip start-position registration which should trigger the
|
||||
// function's default value defined on the database to be applied
|
||||
scope.inTransaction( (em) -> {
|
||||
final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// search-string
|
||||
query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// source-string
|
||||
query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
|
||||
query.setParameter( 1, "." );
|
||||
query.setParameter( 2, "org.hibernate.query" );
|
||||
|
||||
final Object singleResult = query.getSingleResult();
|
||||
assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
assertThat( singleResult ).isEqualTo( 4 );
|
||||
} );
|
||||
}
|
||||
//
|
||||
// @Test
|
||||
// public void testRegisteredParameter(EntityManagerFactoryScope scope) {
|
||||
// // locate takes 2 parameters with an optional 3rd. Here, we will call it
|
||||
// // registering and binding all 3 parameters
|
||||
// scope.inTransaction( (em) -> {
|
||||
// final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
// query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// // search-tring
|
||||
// query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// // source-string
|
||||
// query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
// // start-position
|
||||
// query.registerStoredProcedureParameter( 3, Integer.class, ParameterMode.IN );
|
||||
//
|
||||
// query.setParameter( 1, "." );
|
||||
// query.setParameter( 2, "org.hibernate.query" );
|
||||
// query.setParameter( 3, 5 );
|
||||
//
|
||||
// final Object singleResult = query.getSingleResult();
|
||||
// assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
// assertThat( singleResult ).isEqualTo( 14 );
|
||||
// } );
|
||||
//
|
||||
// // explicit start-position baseline for no-arg
|
||||
//
|
||||
// scope.inTransaction( (em) -> {
|
||||
// final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
// query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// // search-string
|
||||
// query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// // source-string
|
||||
// query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
// // start-position
|
||||
// query.registerStoredProcedureParameter( 3, Integer.class, ParameterMode.IN );
|
||||
//
|
||||
// query.setParameter( 1, "." );
|
||||
// query.setParameter( 2, "org.hibernate.query" );
|
||||
// query.setParameter( 3, 0 );
|
||||
//
|
||||
// final Object singleResult = query.getSingleResult();
|
||||
// assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
// assertThat( singleResult ).isEqualTo( 4 );
|
||||
// } );
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testUnRegisteredParameter(EntityManagerFactoryScope scope) {
|
||||
// // next, skip start-position registration which should trigger the
|
||||
// // function's default value defined on the database to be applied
|
||||
// scope.inTransaction( (em) -> {
|
||||
// final StoredProcedureQuery query = em.createStoredProcedureQuery("locate" );
|
||||
// query.setHint( QueryHints.CALLABLE_FUNCTION, "true" );
|
||||
// // search-string
|
||||
// query.registerStoredProcedureParameter( 1, String.class, ParameterMode.IN );
|
||||
// // source-string
|
||||
// query.registerStoredProcedureParameter( 2, String.class, ParameterMode.IN );
|
||||
//
|
||||
// query.setParameter( 1, "." );
|
||||
// query.setParameter( 2, "org.hibernate.query" );
|
||||
//
|
||||
// final Object singleResult = query.getSingleResult();
|
||||
// assertThat( singleResult ).isInstanceOf( Integer.class );
|
||||
// assertThat( singleResult ).isEqualTo( 4 );
|
||||
// } );
|
||||
// }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue