Skip to content

Commit b8b586a

Browse files
committed
HHH-8477 - Cannot create named queries at runtime - exception results
1 parent d995bb9 commit b8b586a

File tree

3 files changed

+69
-30
lines changed

3 files changed

+69
-30
lines changed

hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerFactoryImpl.java

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -368,26 +368,59 @@ public PersistenceUnitUtil getPersistenceUnitUtil() {
368368
public void addNamedQuery(String name, Query query) {
369369
validateNotClosed();
370370

371-
if ( StoredProcedureQueryImpl.class.isInstance( query ) ) {
372-
final ProcedureCall procedureCall = ( (StoredProcedureQueryImpl) query ).getHibernateProcedureCall();
373-
sessionFactory.getNamedQueryRepository().registerNamedProcedureCallMemento( name, procedureCall.extractMemento( query.getHints() ) );
374-
}
375-
else if ( ! HibernateQuery.class.isInstance( query ) ) {
376-
throw new PersistenceException( "Cannot use query non-Hibernate EntityManager query as basis for named query" );
377-
}
378-
else {
379-
// create and register the proper NamedQueryDefinition...
380-
final org.hibernate.Query hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
381-
if ( org.hibernate.SQLQuery.class.isInstance( hibernateQuery ) ) {
382-
sessionFactory.registerNamedSQLQueryDefinition(
383-
name,
384-
extractSqlQueryDefinition( (org.hibernate.SQLQuery) hibernateQuery, name )
385-
);
371+
// NOTE : we use Query#unwrap here (rather than direct type checking) to account for possibly wrapped
372+
// query implementations
373+
374+
// first, handle StoredProcedureQuery
375+
try {
376+
final StoredProcedureQueryImpl unwrapped = query.unwrap( StoredProcedureQueryImpl.class );
377+
if ( unwrapped != null ) {
378+
addNamedStoredProcedureQuery( name, unwrapped );
379+
return;
386380
}
387-
else {
388-
sessionFactory.registerNamedQueryDefinition( name, extractHqlQueryDefinition( hibernateQuery, name ) );
381+
}
382+
catch ( PersistenceException ignore ) {
383+
// this means 'query' is not a StoredProcedureQueryImpl
384+
}
385+
386+
// then try as a native-SQL or JPQL query
387+
try {
388+
final HibernateQuery unwrapped = query.unwrap( HibernateQuery.class );
389+
if ( unwrapped != null ) {
390+
// create and register the proper NamedQueryDefinition...
391+
final org.hibernate.Query hibernateQuery = ( (HibernateQuery) query ).getHibernateQuery();
392+
if ( org.hibernate.SQLQuery.class.isInstance( hibernateQuery ) ) {
393+
sessionFactory.registerNamedSQLQueryDefinition(
394+
name,
395+
extractSqlQueryDefinition( (org.hibernate.SQLQuery) hibernateQuery, name )
396+
);
397+
}
398+
else {
399+
sessionFactory.registerNamedQueryDefinition( name, extractHqlQueryDefinition( hibernateQuery, name ) );
400+
}
401+
return;
389402
}
390403
}
404+
catch ( PersistenceException ignore ) {
405+
// this means 'query' is not a native-SQL or JPQL query
406+
}
407+
408+
409+
// if we get here, we are unsure how to properly unwrap the incoming query to extract the needed information
410+
throw new PersistenceException(
411+
String.format(
412+
"Unsure how to how to properly unwrap given Query [%s] as basis for named query",
413+
query
414+
)
415+
);
416+
}
417+
418+
private void addNamedStoredProcedureQuery(String name, StoredProcedureQueryImpl query) {
419+
final ProcedureCall procedureCall = query.getHibernateProcedureCall();
420+
sessionFactory.getNamedQueryRepository().registerNamedProcedureCallMemento(
421+
name,
422+
procedureCall.extractMemento( query.getHints() )
423+
);
391424
}
392425

393426
private NamedSQLQueryDefinition extractSqlQueryDefinition(org.hibernate.SQLQuery nativeSqlQuery, String name) {

hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/QueryImpl.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import javax.persistence.ParameterMode;
4242
import javax.persistence.PersistenceException;
4343
import javax.persistence.Query;
44+
import javax.persistence.StoredProcedureQuery;
4445
import javax.persistence.TemporalType;
4546
import javax.persistence.TypedQuery;
4647

@@ -444,19 +445,21 @@ public <T> T unwrap(Class<T> tClass) {
444445
if ( org.hibernate.Query.class.isAssignableFrom( tClass ) ) {
445446
return (T) query;
446447
}
447-
else {
448-
try {
449-
return (T) this;
450-
}
451-
catch ( ClassCastException cce ) {
452-
PersistenceException pe = new PersistenceException(
453-
"Unsupported unwrap target type [" + tClass.getName() + "]"
454-
);
455-
//It's probably against the spec to not mark the tx for rollback but it will be easier for people
456-
//getEntityManager().handlePersistenceException( pe );
457-
throw pe;
458-
}
448+
if ( QueryImpl.class.isAssignableFrom( tClass ) ) {
449+
return (T) this;
459450
}
451+
if ( HibernateQuery.class.isAssignableFrom( tClass ) ) {
452+
return (T) this;
453+
}
454+
455+
throw new PersistenceException(
456+
String.format(
457+
"Unsure how to unwrap %s impl [%s] as requested type [%s]",
458+
Query.class.getSimpleName(),
459+
this.getClass().getName(),
460+
tClass.getName()
461+
)
462+
);
460463
}
461464

462465
@Override

hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,10 @@ public <T> T unwrap(Class<T> cls) {
385385
else if ( ProcedureOutputs.class.isAssignableFrom( cls ) ) {
386386
return (T) outputs();
387387
}
388-
else if ( BaseQueryImpl.class.isAssignableFrom( cls ) ) {
388+
else if ( StoredProcedureQueryImpl.class.isAssignableFrom( cls ) ) {
389+
return (T) this;
390+
}
391+
else if ( StoredProcedureQuery.class.equals( cls ) ) {
389392
return (T) this;
390393
}
391394

0 commit comments

Comments
 (0)