From 29dc2cb8a0ac3e14671a143079d318844f2e1f16 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 3 Jun 2013 13:40:47 +0200 Subject: [PATCH] DATAJPA-350 - Improve EntityManager usage for query validation. SimpleJpaQuery now uses an explicitly created EntityManager instance to verify the manually defined query be able to close the instance explicitly. This will improve GCing the instance. --- .../jpa/repository/query/SimpleJpaQuery.java | 20 +++++++++++++++++- .../JpaQueryLookupStrategyUnitTests.java | 20 +++++++++++------- .../query/SimpleJpaQueryUnitTests.java | 21 +++++++++---------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java index 9c43d281b..fc3130bfb 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java @@ -73,14 +73,32 @@ final class SimpleJpaQuery extends AbstractJpaQuery { } } + /** + * Validates the given query for syntactical correctness. + * + * @param query + * @param em + */ private final void validateQuery(String query, EntityManager em) { + EntityManager validatingEm = null; + try { - em.createQuery(query); + + validatingEm = em.getEntityManagerFactory().createEntityManager(); + validatingEm.createQuery(query); + } catch (RuntimeException e) { + // Needed as there's ambiguities in how an invalid query string shall be expressed by the persistence provider // http://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2012-07/message/17 throw e instanceof IllegalArgumentException ? e : new IllegalArgumentException(e); + + } finally { + + if (validatingEm != null) { + validatingEm.close(); + } } } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java index b7f11a137..312f8a3ca 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,9 @@ import static org.mockito.Mockito.*; import java.lang.reflect.Method; import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -45,12 +47,16 @@ import org.springframework.data.repository.query.QueryLookupStrategy.Key; @RunWith(MockitoJUnitRunner.class) public class JpaQueryLookupStrategyUnitTests { - @Mock - EntityManager em; - @Mock - QueryExtractor extractor; - @Mock - NamedQueries namedQueries; + @Mock EntityManager em; + @Mock EntityManagerFactory emf; + @Mock QueryExtractor extractor; + @Mock NamedQueries namedQueries; + + @Before + public void setUp() { + when(em.getEntityManagerFactory()).thenReturn(emf); + when(emf.createEntityManager()).thenReturn(em); + } /** * @see DATAJPA-226 diff --git a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java index 86889fd10..96e7e7e36 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import java.lang.reflect.Method; import java.util.List; import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; import javax.persistence.TypedQuery; import org.junit.Before; @@ -51,22 +52,20 @@ public class SimpleJpaQueryUnitTests { JpaQueryMethod method; - @Mock - EntityManager em; - @Mock - QueryExtractor extractor; - @Mock - TypedQuery query; - @Mock - RepositoryMetadata metadata; - @Mock - ParameterBinder binder; + @Mock EntityManager em; + @Mock EntityManagerFactory emf; + @Mock QueryExtractor extractor; + @Mock TypedQuery query; + @Mock RepositoryMetadata metadata; + @Mock ParameterBinder binder; @Before public void setUp() throws SecurityException, NoSuchMethodException { when(em.createQuery(anyString())).thenReturn(query); when(em.createQuery(anyString(), eq(Long.class))).thenReturn(query); + when(em.getEntityManagerFactory()).thenReturn(emf); + when(emf.createEntityManager()).thenReturn(em); Method setUp = UserRepository.class.getMethod("findByLastname", String.class); method = new JpaQueryMethod(setUp, metadata, extractor);