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 ;
@@ -389,7 +391,7 @@ public <T> ReactiveNativeQueryImplementor<T> createReactiveNativeQuery(String sq
389391 delayedAfterCompletion ();
390392
391393 try {
392- final ReactiveNativeQueryImpl <T > query = new ReactiveNativeQueryImpl <>( sqlString , this );
394+ final ReactiveNativeQueryImpl <T > query = new ReactiveNativeQueryImpl <>( sqlString , null , this );
393395 if ( isEmpty ( query .getComment () ) ) {
394396 query .setComment ( "dynamic native SQL query" );
395397 }
@@ -445,32 +447,34 @@ public <R> ReactiveNativeQuery<R> createReactiveNativeQuery(String sqlString, Cl
445447 }
446448 }
447449
450+ @ Override
451+ public <R > ReactiveNativeQuery <R > createReactiveNativeQuery (String sqlString , String resultSetMappingName , Class <R > resultClass ) {
452+ final ReactiveNativeQuery <R > query = createReactiveNativeQuery ( sqlString , resultSetMappingName );
453+ if ( Tuple .class .equals ( resultClass ) ) {
454+ query .setTupleTransformer ( new NativeQueryTupleTransformer () );
455+ }
456+ return query ;
457+ }
458+
448459 @ Override
449460 public <R > ReactiveNativeQuery <R > createReactiveNativeQuery (String sqlString , String resultSetMappingName ) {
461+ if ( isEmpty ( resultSetMappingName ) ) {
462+ throw new IllegalArgumentException ( "Result set mapping name was not specified" );
463+ }
464+
450465 checkOpen ();
451466 pulseTransactionCoordinator ();
452467 delayedAfterCompletion ();
453468
454469 try {
455- return isNotEmpty ( resultSetMappingName )
456- ? new ReactiveNativeQueryImpl <>( sqlString , getResultSetMappingMemento ( resultSetMappingName ), this )
457- : new ReactiveNativeQueryImpl <>( sqlString , this );
470+ return new ReactiveNativeQueryImpl <>( sqlString , getResultSetMappingMemento ( resultSetMappingName ), null , this );
458471 //TODO: why no applyQuerySettingsAndHints( query ); ???
459472 }
460473 catch (RuntimeException he ) {
461474 throw getExceptionConverter ().convert ( he );
462475 }
463476 }
464477
465- @ Override
466- public <R > ReactiveNativeQuery <R > createReactiveNativeQuery (String sqlString , String resultSetMappingName , Class <R > resultClass ) {
467- final ReactiveNativeQuery <R > query = createReactiveNativeQuery ( sqlString , resultSetMappingName );
468- if ( Tuple .class .equals ( resultClass ) ) {
469- query .setTupleTransformer ( new NativeQueryTupleTransformer () );
470- }
471- return query ;
472- }
473-
474478 @ Override
475479 public <R > ReactiveSelectionQuery <R > createReactiveSelectionQuery (String hqlString , Class <R > resultType ) {
476480 return interpretAndCreateSelectionQuery ( hqlString , resultType );
@@ -503,9 +507,78 @@ private <R> ReactiveSelectionQuery<R> createSelectionQuery(String hql, Class<R>
503507 return query ;
504508 }
505509
510+ @ Override
511+ public <R > ReactiveQueryImplementor <R > createReactiveNamedQuery (String name ) {
512+ checksBeforeQueryCreation ();
513+ try {
514+ return (ReactiveQueryImplementor <R >) buildNamedQuery (
515+ name ,
516+ this ::createSqmQueryImplementor ,
517+ this ::createNativeQueryImplementor
518+ );
519+ }
520+ catch (RuntimeException e ) {
521+ throw convertNamedQueryException ( e );
522+ }
523+ }
524+
506525 @ Override
507526 public <R > ReactiveQueryImplementor <R > createReactiveNamedQuery (String name , Class <R > resultType ) {
508- return (ReactiveQueryImplementor <R >) buildNamedQuery ( name , resultType );
527+ checksBeforeQueryCreation ();
528+ if ( resultType == null ) {
529+ throw new IllegalArgumentException ( "Result class is null" );
530+ }
531+ try {
532+ return buildNamedQuery (
533+ name ,
534+ memento -> createReactiveSqmQueryImplementor ( resultType , memento ),
535+ memento -> createReactiveNativeQueryImplementor ( resultType , memento )
536+ );
537+ }
538+ catch (RuntimeException e ) {
539+ throw convertNamedQueryException ( e );
540+ }
541+ }
542+
543+ private void checksBeforeQueryCreation () {
544+ checkOpen ();
545+ checkTransactionSynchStatus ();
546+ }
547+
548+ protected <T > ReactiveNativeQueryImpl <T > createReactiveNativeQueryImplementor (Class <T > resultType , NamedNativeQueryMemento <?> memento ) {
549+ final NativeQueryImplementor <T > query = memento .toQuery (this , resultType );
550+ if ( isEmpty ( query .getComment () ) ) {
551+ query .setComment ( "dynamic native SQL query" );
552+ }
553+ applyQuerySettingsAndHints ( query );
554+ return (ReactiveNativeQueryImpl <T >) query ;
555+ }
556+
557+ protected <T > ReactiveQuerySqmImpl <T > createReactiveSqmQueryImplementor (Class <T > resultType , NamedSqmQueryMemento <?> memento ) {
558+ final SqmQueryImplementor <T > query = memento .toQuery ( this , resultType );
559+ if ( isEmpty ( query .getComment () ) ) {
560+ query .setComment ( "dynamic query" );
561+ }
562+ applyQuerySettingsAndHints ( query );
563+ if ( memento .getLockOptions () != null ) {
564+ query .setLockOptions ( memento .getLockOptions () );
565+ }
566+ return (ReactiveQuerySqmImpl <T >) query ;
567+ }
568+
569+ private RuntimeException convertNamedQueryException (RuntimeException e ) {
570+ if ( e instanceof UnknownNamedQueryException ) {
571+ // JPA expects this to mark the transaction for rollback only
572+ getTransactionCoordinator ().getTransactionDriverControl ().markRollbackOnly ();
573+ // it also expects an IllegalArgumentException, so wrap UnknownNamedQueryException
574+ return new IllegalArgumentException ( e .getMessage (), e );
575+ }
576+ else if ( e instanceof IllegalArgumentException ) {
577+ return e ;
578+ }
579+ else {
580+ return getExceptionConverter ().convert ( e );
581+ }
509582 }
510583
511584 @ Override
@@ -590,7 +663,7 @@ public <R> ReactiveNativeQuery<R> createReactiveNativeQuery(String queryString,
590663 delayedAfterCompletion ();
591664
592665 try {
593- final ReactiveNativeQueryImpl <R > query = new ReactiveNativeQueryImpl <>( queryString , this );
666+ final ReactiveNativeQueryImpl <R > query = new ReactiveNativeQueryImpl <>( queryString , null , this );
594667 addAffectedEntities ( affectedEntities , query );
595668 if ( isEmpty ( query .getComment () ) ) {
596669 query .setComment ( "dynamic native SQL query" );
@@ -620,12 +693,11 @@ public <R> ReactiveNativeQueryImpl<R> createReactiveNativeQuery(String queryStri
620693 checkOpen ();
621694 pulseTransactionCoordinator ();
622695 delayedAfterCompletion ();
623-
696+ // Should we throw an exception?
697+ NamedResultSetMappingMemento memento = resultSetMapping == null ? null : getResultSetMappingMemento ( resultSetMapping .getName () );
624698 try {
625699 // Same approach as AbstractSharedSessionContract#createNativeQuery(String, String)
626- final ReactiveNativeQueryImpl <R > nativeQuery = resultSetMapping != null
627- ? new ReactiveNativeQueryImpl <>( queryString , getResultSetMappingMemento ( resultSetMapping .getName () ), this )
628- : new ReactiveNativeQueryImpl <>( queryString , this );
700+ final ReactiveNativeQueryImpl <R > nativeQuery = new ReactiveNativeQueryImpl <>( queryString , memento , null , this );
629701 applyQuerySettingsAndHints ( nativeQuery );
630702 return nativeQuery ;
631703 }
@@ -650,20 +722,13 @@ public <T> ResultSetMapping<T> getResultSetMapping(Class<T> resultType, String m
650722 if ( mapping == null ) {
651723 throw new IllegalArgumentException ( "result set mapping does not exist: " + mappingName );
652724 }
653- //
654- // ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl( "impl" );
655- // if ( resultType != null ) {
656- // Class<?> mappedResultType = resultSetMapping.;
657- // if ( !resultType.equals( mappedResultType ) ) {
658- // throw new IllegalArgumentException( "incorrect result type for result set mapping: " + mappingName + " has type " + mappedResultType.getName() );
659- // }
660- // }
661725
662726 return new ResultSetMapping <>() {
663727 @ Override
664728 public String getName () {
665729 return mappingName ;
666730 }
731+
667732 @ Override
668733 public Class <T > getResultType () {
669734 return resultType ;
0 commit comments