7272import org .hibernate .proxy .HibernateProxy ;
7373import org .hibernate .proxy .LazyInitializer ;
7474import org .hibernate .query .IllegalMutationQueryException ;
75+ import org .hibernate .query .UnknownNamedQueryException ;
7576import org .hibernate .query .criteria .JpaCriteriaInsert ;
7677import org .hibernate .query .hql .spi .SqmQueryImplementor ;
7778import org .hibernate .query .named .NamedResultSetMappingMemento ;
7879import org .hibernate .query .spi .HqlInterpretation ;
7980import org .hibernate .query .spi .QueryImplementor ;
81+ import org .hibernate .query .sql .spi .NamedNativeQueryMemento ;
8082import org .hibernate .query .sql .spi .NativeQueryImplementor ;
8183import org .hibernate .query .sqm .internal .SqmUtil ;
84+ import org .hibernate .query .sqm .spi .NamedSqmQueryMemento ;
8285import org .hibernate .query .sqm .tree .SqmStatement ;
8386import org .hibernate .query .sqm .tree .delete .SqmDeleteStatement ;
8487import org .hibernate .query .sqm .tree .insert .SqmInsertStatement ;
131134import static org .hibernate .engine .spi .NaturalIdResolutions .INVALID_NATURAL_ID_REFERENCE ;
132135import static org .hibernate .event .spi .LoadEventListener .IMMEDIATE_LOAD ;
133136import static org .hibernate .internal .util .StringHelper .isEmpty ;
134- import static org .hibernate .internal .util .StringHelper .isNotEmpty ;
135137import static org .hibernate .proxy .HibernateProxy .extractLazyInitializer ;
136138import static org .hibernate .reactive .common .InternalStateAssertions .assertUseOnEventLoop ;
137139import static org .hibernate .reactive .persister .entity .impl .ReactiveEntityPersister .forceInitialize ;
@@ -387,7 +389,7 @@ public <T> ReactiveNativeQueryImplementor<T> createReactiveNativeQuery(String sq
387389 delayedAfterCompletion ();
388390
389391 try {
390- final ReactiveNativeQueryImpl <T > query = new ReactiveNativeQueryImpl <>( sqlString , this );
392+ final ReactiveNativeQueryImpl <T > query = new ReactiveNativeQueryImpl <>( sqlString , mthis );
391393 if ( isEmpty ( query .getComment () ) ) {
392394 query .setComment ( "dynamic native SQL query" );
393395 }
@@ -443,14 +445,16 @@ public <R> ReactiveNativeQuery<R> createReactiveNativeQuery(String sqlString, Cl
443445
444446 @ Override @ Deprecated (forRemoval = true )
445447 public <R > ReactiveNativeQuery <R > createReactiveNativeQuery (String sqlString , String resultSetMappingName ) {
448+ if ( isEmpty ( resultSetMappingName ) ) {
449+ throw new IllegalArgumentException ( "Result set mapping name was not specified" );
450+ }
451+
446452 checkOpen ();
447453 pulseTransactionCoordinator ();
448454 delayedAfterCompletion ();
449455
450456 try {
451- return isNotEmpty ( resultSetMappingName )
452- ? new ReactiveNativeQueryImpl <>( sqlString , getResultSetMappingMemento ( resultSetMappingName ), this )
453- : new ReactiveNativeQueryImpl <>( sqlString , this );
457+ return new ReactiveNativeQueryImpl <>( sqlString , getResultSetMappingMemento ( resultSetMappingName ), null , this );
454458 //TODO: why no applyQuerySettingsAndHints( query ); ???
455459 }
456460 catch (RuntimeException he ) {
@@ -497,9 +501,78 @@ private <R> ReactiveSelectionQuery<R> createSelectionQuery(String hql, Class<R>
497501 return query ;
498502 }
499503
504+ @ Override
505+ public <R > ReactiveQueryImplementor <R > createReactiveNamedQuery (String name ) {
506+ checksBeforeQueryCreation ();
507+ try {
508+ return (ReactiveQueryImplementor <R >) buildNamedQuery (
509+ name ,
510+ this ::createSqmQueryImplementor ,
511+ this ::createNativeQueryImplementor
512+ );
513+ }
514+ catch (RuntimeException e ) {
515+ throw convertNamedQueryException ( e );
516+ }
517+ }
518+
500519 @ Override
501520 public <R > ReactiveQueryImplementor <R > createReactiveNamedQuery (String name , Class <R > resultType ) {
502- return (ReactiveQueryImplementor <R >) buildNamedQuery ( name , resultType );
521+ checksBeforeQueryCreation ();
522+ if ( resultType == null ) {
523+ throw new IllegalArgumentException ( "Result class is null" );
524+ }
525+ try {
526+ return buildNamedQuery (
527+ name ,
528+ memento -> createReactiveSqmQueryImplementor ( resultType , memento ),
529+ memento -> createReactiveNativeQueryImplementor ( resultType , memento )
530+ );
531+ }
532+ catch (RuntimeException e ) {
533+ throw convertNamedQueryException ( e );
534+ }
535+ }
536+
537+ private void checksBeforeQueryCreation () {
538+ checkOpen ();
539+ checkTransactionSynchStatus ();
540+ }
541+
542+ protected <T > ReactiveNativeQueryImpl <T > createReactiveNativeQueryImplementor (Class <T > resultType , NamedNativeQueryMemento <?> memento ) {
543+ final NativeQueryImplementor <T > query = memento .toQuery (this , resultType );
544+ if ( isEmpty ( query .getComment () ) ) {
545+ query .setComment ( "dynamic native SQL query" );
546+ }
547+ applyQuerySettingsAndHints ( query );
548+ return (ReactiveNativeQueryImpl <T >) query ;
549+ }
550+
551+ protected <T > ReactiveQuerySqmImpl <T > createReactiveSqmQueryImplementor (Class <T > resultType , NamedSqmQueryMemento <?> memento ) {
552+ final SqmQueryImplementor <T > query = memento .toQuery ( this , resultType );
553+ if ( isEmpty ( query .getComment () ) ) {
554+ query .setComment ( "dynamic query" );
555+ }
556+ applyQuerySettingsAndHints ( query );
557+ if ( memento .getLockOptions () != null ) {
558+ query .setLockOptions ( memento .getLockOptions () );
559+ }
560+ return (ReactiveQuerySqmImpl <T >) query ;
561+ }
562+
563+ private RuntimeException convertNamedQueryException (RuntimeException e ) {
564+ if ( e instanceof UnknownNamedQueryException ) {
565+ // JPA expects this to mark the transaction for rollback only
566+ getTransactionCoordinator ().getTransactionDriverControl ().markRollbackOnly ();
567+ // it also expects an IllegalArgumentException, so wrap UnknownNamedQueryException
568+ return new IllegalArgumentException ( e .getMessage (), e );
569+ }
570+ else if ( e instanceof IllegalArgumentException ) {
571+ return e ;
572+ }
573+ else {
574+ return getExceptionConverter ().convert ( e );
575+ }
503576 }
504577
505578 @ Override
@@ -584,7 +657,7 @@ public <R> ReactiveNativeQuery<R> createReactiveNativeQuery(String queryString,
584657 delayedAfterCompletion ();
585658
586659 try {
587- final ReactiveNativeQueryImpl <R > query = new ReactiveNativeQueryImpl <>( queryString , this );
660+ final ReactiveNativeQueryImpl <R > query = new ReactiveNativeQueryImpl <>( queryString , null , this );
588661 addAffectedEntities ( affectedEntities , query );
589662 if ( isEmpty ( query .getComment () ) ) {
590663 query .setComment ( "dynamic native SQL query" );
@@ -622,12 +695,11 @@ public <R> ReactiveNativeQueryImpl<R> createReactiveNativeQuery(String queryStri
622695 checkOpen ();
623696 pulseTransactionCoordinator ();
624697 delayedAfterCompletion ();
625-
698+ // Should we throw an exception?
699+ NamedResultSetMappingMemento memento = resultSetMapping == null ? null : getResultSetMappingMemento ( resultSetMapping .getName () );
626700 try {
627701 // Same approach as AbstractSharedSessionContract#createNativeQuery(String, String)
628- final ReactiveNativeQueryImpl <R > nativeQuery = resultSetMapping != null
629- ? new ReactiveNativeQueryImpl <>( queryString , getResultSetMappingMemento ( resultSetMapping .getName () ), this )
630- : new ReactiveNativeQueryImpl <>( queryString , this );
702+ final ReactiveNativeQueryImpl <R > nativeQuery = new ReactiveNativeQueryImpl <>( queryString , memento , null , this );
631703 applyQuerySettingsAndHints ( nativeQuery );
632704 return nativeQuery ;
633705 }
@@ -652,20 +724,13 @@ public <T> ResultSetMapping<T> getResultSetMapping(Class<T> resultType, String m
652724 if ( mapping == null ) {
653725 throw new IllegalArgumentException ( "result set mapping does not exist: " + mappingName );
654726 }
655- //
656- // ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl( "impl" );
657- // if ( resultType != null ) {
658- // Class<?> mappedResultType = resultSetMapping.;
659- // if ( !resultType.equals( mappedResultType ) ) {
660- // throw new IllegalArgumentException( "incorrect result type for result set mapping: " + mappingName + " has type " + mappedResultType.getName() );
661- // }
662- // }
663727
664728 return new ResultSetMapping <>() {
665729 @ Override
666730 public String getName () {
667731 return mappingName ;
668732 }
733+
669734 @ Override
670735 public Class <T > getResultType () {
671736 return resultType ;
0 commit comments