From a666ac0dac9450c4f0c99bcad549edf9b996a94a Mon Sep 17 00:00:00 2001 From: rmartinc Date: Thu, 2 Sep 2021 10:55:40 +0200 Subject: [PATCH] HHH-14796 Cannot replace an existing JPQL NamedQuery with a native NamedQuery --- .../query/spi/NamedQueryRepository.java | 18 ++++++++++ .../jpa/test/query/AddNamedQueryTest.java | 35 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/NamedQueryRepository.java b/hibernate-core/src/main/java/org/hibernate/query/spi/NamedQueryRepository.java index 72e1f70aae..c25cb5243d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/NamedQueryRepository.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/NamedQueryRepository.java @@ -92,6 +92,14 @@ public class NamedQueryRepository { return namedSqlResultSetMappingMap.get( mappingName ); } + private synchronized void removeNamedQueryDefinition(String name) { + if ( this.namedQueryDefinitionMap.containsKey( name ) ) { + final Map copy = CollectionHelper.makeCopy( namedQueryDefinitionMap ); + copy.remove( name ); + this.namedQueryDefinitionMap = toSmallMap( copy ); + } + } + public synchronized void registerNamedQueryDefinition(String name, NamedQueryDefinition definition) { if ( NamedSQLQueryDefinition.class.isInstance( definition ) ) { throw new IllegalArgumentException( "NamedSQLQueryDefinition instance incorrectly passed to registerNamedQueryDefinition" ); @@ -112,6 +120,15 @@ public class NamedQueryRepository { } this.namedQueryDefinitionMap = toSmallMap( copy ); + removeNamedSQLQueryDefinition( name ); + } + + private synchronized void removeNamedSQLQueryDefinition(String name) { + if ( this.namedSqlQueryDefinitionMap.containsKey( name ) ) { + final Map copy = CollectionHelper.makeCopy( namedSqlQueryDefinitionMap ); + copy.remove( name ); + this.namedSqlQueryDefinitionMap = toSmallMap( copy ); + } } public synchronized void registerNamedSQLQueryDefinition(String name, NamedSQLQueryDefinition definition) { @@ -130,6 +147,7 @@ public class NamedQueryRepository { } this.namedSqlQueryDefinitionMap = toSmallMap( copy ); + removeNamedQueryDefinition( name ); } public synchronized void registerNamedProcedureCallMemento(String name, ProcedureCallMemento memento) { diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/query/AddNamedQueryTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/query/AddNamedQueryTest.java index 5921fa508c..8fa7aa71ef 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/query/AddNamedQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/query/AddNamedQueryTest.java @@ -54,6 +54,41 @@ public class AddNamedQueryTest extends BaseEntityManagerFunctionalTestCase { em.close(); } + @Test + public void replaceTest() { + EntityManager em = getOrCreateEntityManager(); + final String name = "myReplaceItemQuery"; + + // create a jpql query + String sql = "from Item"; + Query query = em.createQuery( sql ); + query.setHint( "org.hibernate.comment", sql ); + em.getEntityManagerFactory().addNamedQuery( name, query ); + query = em.createNamedQuery( name ); + assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) ); + assertEquals( 0, query.getResultList().size() ); + + // create a native query and replace the previous jpql + sql = "select * from Item"; + query = em.createNativeQuery( sql, Item.class ); + query.setHint( "org.hibernate.comment", sql ); + em.getEntityManagerFactory().addNamedQuery( name, query ); + query = em.createNamedQuery( name ); + assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) ); + assertEquals( 0, query.getResultList().size() ); + + // define back a named query + sql = "from Item"; + query = em.createQuery( sql ); + query.setHint( "org.hibernate.comment", sql ); + em.getEntityManagerFactory().addNamedQuery( name, query ); + query = em.createNamedQuery( name ); + assertEquals( sql, query.getHints().get( "org.hibernate.comment" ) ); + assertEquals( 0, query.getResultList().size() ); + + em.close(); + } + @Test public void testLockModeHandling() { final String name = "lock-mode-handling";