From: Juergen H. <jho...@us...> - 2008-10-20 22:10:42
|
Update of /cvsroot/springframework/spring/tiger/src/org/springframework/orm/jpa In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv12809/tiger/src/org/springframework/orm/jpa Modified Files: SharedEntityManagerCreator.java Log Message: @PersistenceContext of type TRANSACTION allows returned Query objects to be parameterized and executed as well Index: SharedEntityManagerCreator.java =================================================================== RCS file: /cvsroot/springframework/spring/tiger/src/org/springframework/orm/jpa/SharedEntityManagerCreator.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** SharedEntityManagerCreator.java 29 May 2008 00:35:13 -0000 1.9 --- SharedEntityManagerCreator.java 20 Oct 2008 22:10:36 -0000 1.10 *************** *** 25,28 **** --- 25,29 ---- import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; + import javax.persistence.Query; import org.apache.commons.logging.Log; *************** *** 195,199 **** // Invoke method on current EntityManager. try { ! return method.invoke(target, args); } catch (InvocationTargetException ex) { --- 196,206 ---- // Invoke method on current EntityManager. try { ! Object result = method.invoke(target, args); ! if (isNewEm && result instanceof Query) { ! result = Proxy.newProxyInstance(Query.class.getClassLoader(), new Class[] {Query.class}, ! new DeferredQueryInvocationHandler((Query) result, target)); ! isNewEm = false; ! } ! return result; } catch (InvocationTargetException ex) { *************** *** 208,210 **** --- 215,261 ---- } + + /** + * Invocation handler that handles deferred Query objects created by + * non-transactional createQuery invocations on a shared EntityManager. + */ + private static class DeferredQueryInvocationHandler implements InvocationHandler { + + private final Query target; + + private final EntityManager em; + + private DeferredQueryInvocationHandler(Query target, EntityManager em) { + this.target = target; + this.em = em; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Invocation on Query interface coming in... + + if (method.getName().equals("equals")) { + // Only consider equal when proxies are identical. + return (proxy == args[0]); + } + else if (method.getName().equals("hashCode")) { + // Use hashCode of EntityManager proxy. + return hashCode(); + } + + // Invoke method on actual Query object. + try { + return method.invoke(this.target, args); + } + catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + finally { + if (method.getName().equals("getResultList") || method.getName().equals("getSingleResult") || + method.getName().equals("executeUpdate")) { + EntityManagerFactoryUtils.closeEntityManager(this.em); + } + } + } + } + } |