DeferredQueryInvocationHandler explicitly closes its EntityManager on garbage collection
Includes javadoc revision covering all supported EntityManager types as of JPA 2.1. Issue: SPR-11451
This commit is contained in:
parent
fbd25467c4
commit
a8577da30c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
@ -44,24 +44,37 @@ import org.springframework.util.ClassUtils;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Factory for dynamic EntityManager proxies that follow the JPA spec's
|
||||
* semantics for "extended" EntityManagers.
|
||||
* Delegate for creating a variety of {@link javax.persistence.EntityManager}
|
||||
* proxies that follow the JPA spec's semantics for "extended" EntityManagers.
|
||||
*
|
||||
* <p>Supports explicit joining of a transaction through the
|
||||
* {@code joinTransaction()} method ("application-managed extended
|
||||
* EntityManager") as well as automatic joining on each operation
|
||||
* ("container-managed extended EntityManager").
|
||||
* <p>Supports several different variants of "extended" EntityManagers:
|
||||
* in particular, an "application-managed extended EntityManager", as defined
|
||||
* by {@link javax.persistence.EntityManagerFactory#createEntityManager()},
|
||||
* as well as a "container-managed extended EntityManager", as defined by
|
||||
* {@link javax.persistence.PersistenceContextType#EXTENDED}.
|
||||
*
|
||||
* <p>The original difference between "application-managed" and "container-managed"
|
||||
* was the need for explicit joining of an externally managed transaction through
|
||||
* the {@link EntityManager#joinTransaction()} method in the "application" case
|
||||
* versus the automatic joining on each user-level EntityManager operation in the
|
||||
* "container" case. As of JPA 2.1, both join modes are available with both kinds of
|
||||
* EntityManagers, so the difference between "application-" and "container-managed"
|
||||
* is now primarily in the join mode default and in the restricted lifecycle of a
|
||||
* container-managed EntityManager (i.e. tied to the object that it is injected into).
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see javax.persistence.EntityManagerFactory#createEntityManager()
|
||||
* @see javax.persistence.PersistenceContextType#EXTENDED
|
||||
* @see javax.persistence.EntityManager#joinTransaction()
|
||||
* @see SharedEntityManagerCreator
|
||||
*/
|
||||
public abstract class ExtendedEntityManagerCreator {
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the {@code joinTransaction()}
|
||||
* method, but is not automatically managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* Create an application-managed extended EntityManager proxy.
|
||||
* @param rawEntityManager the raw EntityManager to decorate
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @return an application-managed EntityManager that can join transactions
|
||||
|
@ -74,9 +87,8 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the {@code joinTransaction()}
|
||||
* method, but is not automatically managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* Create an application-managed extended EntityManager proxy.
|
||||
* @param rawEntityManager the raw EntityManager to decorate
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||
|
@ -91,9 +103,8 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager whose lifecycle is managed by the container and which
|
||||
* automatically joins a transaction when being invoked within its scope.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* Create a container-managed extended EntityManager proxy.
|
||||
* @param rawEntityManager the raw EntityManager to decorate
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
|
@ -106,8 +117,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager whose lifecycle is managed by the container and which
|
||||
* automatically joins a transaction when being invoked within its scope.
|
||||
* Create a container-managed extended EntityManager proxy.
|
||||
* @param emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
|
@ -120,8 +130,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager whose lifecycle is managed by the container and which
|
||||
* automatically joins a transaction when being invoked within its scope.
|
||||
* Create a container-managed extended EntityManager proxy.
|
||||
* @param emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
|
@ -136,8 +145,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager whose lifecycle is managed by the container and which
|
||||
* may automatically join a transaction when being invoked within its scope.
|
||||
* Create a container-managed extended EntityManager proxy.
|
||||
* @param emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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,32 +24,38 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Factory for a shareable JPA {@link javax.persistence.EntityManager}
|
||||
* for a given {@link javax.persistence.EntityManagerFactory}.
|
||||
* Delegate for creating a shareable JPA {@link javax.persistence.EntityManager}
|
||||
* reference for a given {@link javax.persistence.EntityManagerFactory}.
|
||||
*
|
||||
* <p>The shareable EntityManager will behave just like an EntityManager fetched
|
||||
* from an application server's JNDI environment, as defined by the JPA
|
||||
* specification. It will delegate all calls to the current transactional
|
||||
* EntityManager, if any; otherwise it will fall back to a newly created
|
||||
* EntityManager per operation.
|
||||
* <p>A shared EntityManager will behave just like an EntityManager fetched from
|
||||
* an application server's JNDI environment, as defined by the JPA specification.
|
||||
* It will delegate all calls to the current transactional EntityManager, if any;
|
||||
* otherwise it will fall back to a newly created EntityManager per operation.
|
||||
*
|
||||
* <p>For a behavioral definition of such a shared transactional EntityManager,
|
||||
* see {@link javax.persistence.PersistenceContextType#TRANSACTION} and its
|
||||
* discussion in the JPA spec document. This is also the default being used
|
||||
* for the annotation-based {@link javax.persistence.PersistenceContext#type()}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @author Oliver Gierke
|
||||
* @since 2.0
|
||||
* @see org.springframework.orm.jpa.LocalEntityManagerFactoryBean
|
||||
* @see javax.persistence.PersistenceContext
|
||||
* @see javax.persistence.PersistenceContextType#TRANSACTION
|
||||
* @see org.springframework.orm.jpa.JpaTransactionManager
|
||||
* @see ExtendedEntityManagerCreator
|
||||
*/
|
||||
public abstract class SharedEntityManagerCreator {
|
||||
|
||||
|
@ -57,8 +63,7 @@ public abstract class SharedEntityManagerCreator {
|
|||
|
||||
|
||||
/**
|
||||
* Create a transactional EntityManager proxy for the given EntityManagerFactory,
|
||||
* automatically joining ongoing transactions.
|
||||
* Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
||||
* @param emf the EntityManagerFactory to delegate to.
|
||||
* @return a shareable transaction EntityManager proxy
|
||||
*/
|
||||
|
@ -296,7 +301,7 @@ public abstract class SharedEntityManagerCreator {
|
|||
|
||||
private final Query target;
|
||||
|
||||
private final EntityManager em;
|
||||
private EntityManager em;
|
||||
|
||||
public DeferredQueryInvocationHandler(Query target, EntityManager em) {
|
||||
this.target = target;
|
||||
|
@ -334,10 +339,22 @@ public abstract class SharedEntityManagerCreator {
|
|||
finally {
|
||||
if (method.getName().equals("getResultList") || method.getName().equals("getSingleResult") ||
|
||||
method.getName().equals("executeUpdate")) {
|
||||
// Actual execution of the query: close the EntityManager right
|
||||
// afterwards, since that was the only reason we kept it open.
|
||||
EntityManagerFactoryUtils.closeEntityManager(this.em);
|
||||
this.em = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
// Trigger explicit EntityManager.close() call on garbage collection,
|
||||
// in particular for open/close statistics to be in sync. This is
|
||||
// only relevant if the Query object has not been executed, e.g.
|
||||
// when just used for the early validation of query definitions.
|
||||
EntityManagerFactoryUtils.closeEntityManager(this.em);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue