diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java index b50d836de..26c2f42d2 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java @@ -41,6 +41,7 @@ import org.apache.openjpa.kernel.jpql.JPQLParser; import org.apache.openjpa.lib.jdbc.AbstractJDBCListener; import org.apache.openjpa.lib.jdbc.JDBCEvent; import org.apache.openjpa.lib.jdbc.JDBCListener; +import org.apache.openjpa.persistence.OpenJPAEntityManager; import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; import org.apache.openjpa.persistence.OpenJPAPersistence; @@ -780,6 +781,32 @@ public class TestPreparedQueryCache extends TestCase { em.getTransaction().rollback(); } + public void testMultithreadedAccess() { + OpenJPAEntityManager em1 = emf.createEntityManager(); + String jpql = "select p from Author p where p.name=:name"; + int N = 5; + Thread[] threads = new Thread[N]; + QueryThread[] qts = new QueryThread[N]; + for (int i = 0; i < N; i++) { + OpenJPAEntityManager emt = emf.createEntityManager(); + qts[i] = new QueryThread(emt, jpql); + threads[i] = new Thread(qts[i]); + threads[i].setDaemon(true); + } + for (Thread t : threads) { + t.start(); + } + for (int i = 0; i < N; i++) { + try { + threads[i].join(); + assertFalse(qts[i].isFailed()); + } catch (InterruptedException e) { + e.printStackTrace(); + fail(); + } + } + } + PreparedQueryCache getPreparedQueryCache() { return emf.getConfiguration().getQuerySQLCacheInstance(); @@ -967,5 +994,36 @@ public class TestPreparedQueryCache extends TestCase { return new ArrayList(sqls); } } + + public static class QueryThread implements Runnable { + private final OpenJPAEntityManager em; + private final String jpql; + private boolean failed = false; + public QueryThread(OpenJPAEntityManager em, String jpql) { + super(); + this.em = em; + this.jpql = jpql; + } + + public void run() { + try { + for (int i = 0; i < 10 && !failed; i++) { + OpenJPAQuery q = em.createQuery(jpql); + q.setParameter("name", "Author-"+i); + q.getResultList(); + if (i > 1) + assertEquals(QueryLanguages.LANG_PREPARED_SQL, q.getLanguage()); + } + } catch (Exception e) { + e.printStackTrace(); + failed = true; + } + } + + public boolean isFailed() { + return failed; + } + + } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java index 56f531a8d..357a6e744 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java @@ -963,7 +963,7 @@ public class EntityManagerImpl String qid = query; PreparedQuery pq = JPQLParser.LANG_JPQL.equals(language) ? getPreparedQuery(qid) : null; - org.apache.openjpa.kernel.Query q = (pq == null) + org.apache.openjpa.kernel.Query q = (pq == null || !pq.isInitialized()) ? _broker.newQuery(language, query) : _broker.newQuery(pq.getLanguage(), pq); // have to validate JPQL according to spec @@ -1003,7 +1003,7 @@ public class EntityManagerImpl PreparedQuery pq = JPQLParser.LANG_JPQL.equals(meta.getLanguage()) ? getPreparedQuery(qid) : null; - org.apache.openjpa.kernel.Query del = (pq == null) + org.apache.openjpa.kernel.Query del = (pq == null || !pq.isInitialized()) ? _broker.newQuery(meta.getLanguage(), meta.getQueryString()) : _broker.newQuery(pq.getLanguage(), pq);