|
23 | 23 | import java.lang.reflect.InvocationTargetException;
|
24 | 24 | import java.lang.reflect.Method;
|
25 | 25 | import java.lang.reflect.Proxy;
|
| 26 | +import java.util.HashSet; |
26 | 27 | import java.util.Map;
|
| 28 | +import java.util.Set; |
27 | 29 | import javax.persistence.EntityManager;
|
28 | 30 | import javax.persistence.EntityManagerFactory;
|
29 | 31 | import javax.persistence.Query;
|
| 32 | +import javax.persistence.TransactionRequiredException; |
30 | 33 |
|
31 | 34 | import org.apache.commons.logging.Log;
|
32 | 35 | import org.apache.commons.logging.LogFactory;
|
@@ -61,6 +64,23 @@ public abstract class SharedEntityManagerCreator {
|
61 | 64 |
|
62 | 65 | private static final Class<?>[] NO_ENTITY_MANAGER_INTERFACES = new Class<?>[0];
|
63 | 66 |
|
| 67 | + private static final Set<String> transactionRequiringMethods = new HashSet<String>(6); |
| 68 | + |
| 69 | + private static final Set<String> queryTerminationMethods = new HashSet<String>(3); |
| 70 | + |
| 71 | + static { |
| 72 | + transactionRequiringMethods.add("joinTransaction"); |
| 73 | + transactionRequiringMethods.add("flush"); |
| 74 | + transactionRequiringMethods.add("persist"); |
| 75 | + transactionRequiringMethods.add("merge"); |
| 76 | + transactionRequiringMethods.add("remove"); |
| 77 | + transactionRequiringMethods.add("refresh"); |
| 78 | + |
| 79 | + queryTerminationMethods.add("getResultList"); |
| 80 | + queryTerminationMethods.add("getSingleResult"); |
| 81 | + queryTerminationMethods.add("executeUpdate"); |
| 82 | + } |
| 83 | + |
64 | 84 |
|
65 | 85 | /**
|
66 | 86 | * Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
@@ -246,6 +266,13 @@ else if (method.getName().equals("unwrap")) {
|
246 | 266 | }
|
247 | 267 | // Still perform unwrap call on target EntityManager.
|
248 | 268 | }
|
| 269 | + else if (transactionRequiringMethods.contains(method.getName())) { |
| 270 | + // We need a transactional target now, according to the JPA spec. |
| 271 | + // Otherwise, the operation would get accepted but remain unflushed... |
| 272 | + if (target == null) { |
| 273 | + throw new TransactionRequiredException("No transactional EntityManager available"); |
| 274 | + } |
| 275 | + } |
249 | 276 |
|
250 | 277 | // Regular EntityManager operations.
|
251 | 278 | boolean isNewEm = false;
|
@@ -337,8 +364,7 @@ else if (method.getName().equals("unwrap")) {
|
337 | 364 | throw ex.getTargetException();
|
338 | 365 | }
|
339 | 366 | finally {
|
340 |
| - if (method.getName().equals("getResultList") || method.getName().equals("getSingleResult") || |
341 |
| - method.getName().equals("executeUpdate")) { |
| 367 | + if (queryTerminationMethods.contains(method.getName())) { |
342 | 368 | // Actual execution of the query: close the EntityManager right
|
343 | 369 | // afterwards, since that was the only reason we kept it open.
|
344 | 370 | EntityManagerFactoryUtils.closeEntityManager(this.em);
|
|
0 commit comments