| 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.
|