_emphasized text_ *Problem:* Thread-unsafe behavior of query spaces in named queries I catch *ConcurrentModificationException* sometimes when execute Native Queries.
*Information:* # *emf.addNamedQuery* When we want to save Query with defined name we should use EntityManagerFactory#addNamedQuery This method build new NamedSQLQueryDefinition from saved Query. NamedSQLQueryDefinition created by NamedSQLQueryDefinitionBuilder # *NamedSQLQueryDefinitionBuilder* NamedSQLQueryDefinitionBuilder use method createNamedQueryDefinition for NamedSQLQueryDefinition build. This method use querySpacesCopy() for safe copying of elements from querySpaces. # *em.createNamedQuery* When we want to create new instance of Query by name we should use EntityManager#createNamedQuery We get NamedSQLQueryDefinition from NamedQueryRepository by query name. +Version 5.1.14:+ Our new query (new SQLQueryImpl) will get NamedSQLQueryDefinition Also, new query get all query spaces: this.querySpaces = queryDef.getQuerySpaces(); +Version 5.3.0:+ The same behavior in NativeQueryImpl class # *Thead-safe or not Thread-safe?* SQLQueryImpl copy reference to NamedSQLQueryDefinition query spaces collection, not makes copy (like NamedSQLQueryDefinitionBuilder). So, every Named Query created by the same name share one query spaces collection. It's not thread safe, not obvious and unpredictably.
*Suggestion:* create copy of query spaces in SQLQueryImpl constructor with NamedSQLQueryDefinition
*Links*: +Version 5.1.14 source code+: https://github.com/hibernate/hibernate-orm/blob/5.1.14/hibernate-core/src/main/java/org/hibernate/internal/SQLQueryImpl.java#L85 +Version 5.3.0.Final source code+: https://github.com/hibernate/hibernate-orm/blob/5.3.0.Final/hibernate-core/src/main/java/org/hibernate/query/internal/NativeQueryImpl.java#L85
To reproduce the error: # Import Gradle project from [^HibernateThreadUnsafeSample.rar] # Perform tests from AppTest test class. |
|