Removed deprecated JpaTemplate and JpaInterceptor classes; dropped unused EntityManager(Factory)Plus mechanism
This commit is contained in:
parent
7ceb02257e
commit
9caa514c69
|
@ -110,8 +110,6 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
|||
/** Raw EntityManagerFactory as returned by the PersistenceProvider */
|
||||
public EntityManagerFactory nativeEntityManagerFactory;
|
||||
|
||||
private EntityManagerFactoryPlusOperations plusOperations;
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
|
||||
|
@ -339,10 +337,6 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
|||
ifcs.addAll(ClassUtils.getAllInterfacesForClassAsSet(emf.getClass(), this.beanClassLoader));
|
||||
}
|
||||
ifcs.add(EntityManagerFactoryInfo.class);
|
||||
if (getJpaDialect() != null && getJpaDialect().supportsEntityManagerFactoryPlusOperations()) {
|
||||
this.plusOperations = getJpaDialect().getEntityManagerFactoryPlusOperations(emf);
|
||||
ifcs.add(EntityManagerFactoryPlusOperations.class);
|
||||
}
|
||||
try {
|
||||
return (EntityManagerFactory) Proxy.newProxyInstance(
|
||||
this.beanClassLoader, ifcs.toArray(new Class[ifcs.size()]),
|
||||
|
@ -363,16 +357,13 @@ public abstract class AbstractEntityManagerFactoryBean implements
|
|||
}
|
||||
|
||||
/**
|
||||
* Delegate an incoming invocation from the proxy, dispatching to EntityManagerFactoryInfo /
|
||||
* EntityManagerFactoryPlusOperations / the native EntityManagerFactory accordingly.
|
||||
* Delegate an incoming invocation from the proxy, dispatching to EntityManagerFactoryInfo
|
||||
* or the native EntityManagerFactory accordingly.
|
||||
*/
|
||||
Object invokeProxyMethod(Method method, Object[] args) throws Throwable {
|
||||
if (method.getDeclaringClass().isAssignableFrom(EntityManagerFactoryInfo.class)) {
|
||||
return method.invoke(this, args);
|
||||
}
|
||||
else if (method.getDeclaringClass().equals(EntityManagerFactoryPlusOperations.class)) {
|
||||
return method.invoke(this.plusOperations, args);
|
||||
}
|
||||
else if (method.getName().equals("createEntityManager") && args != null && args.length > 0 &&
|
||||
args[0] != null && args[0].getClass().isEnum() && "SYNCHRONIZED".equals(args[0].toString())) {
|
||||
// JPA 2.1's createEntityManager(SynchronizationType, Map)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
|
@ -18,9 +18,7 @@ package org.springframework.orm.jpa;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
@ -31,23 +29,20 @@ import org.springframework.transaction.TransactionException;
|
|||
|
||||
/**
|
||||
* Default implementation of the {@link JpaDialect} interface.
|
||||
* Used as default dialect by {@link JpaAccessor} and {@link JpaTransactionManager}.
|
||||
* Used as default dialect by {@link JpaTransactionManager}.
|
||||
*
|
||||
* <p>Simply begins a standard JPA transaction in {@link #beginTransaction}
|
||||
* and performs standard exception translation through {@link EntityManagerFactoryUtils}.
|
||||
*
|
||||
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see JpaAccessor#setJpaDialect
|
||||
* @see JpaTransactionManager#setJpaDialect
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DefaultJpaDialect implements JpaDialect, Serializable {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Hooks for transaction management (used by JpaTransactionManager)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This implementation invokes the standard JPA {@code Transaction.begin}
|
||||
* method. Throws an InvalidIsolationLevelException if a non-default isolation
|
||||
|
@ -110,7 +105,7 @@ public class DefaultJpaDialect implements JpaDialect, Serializable {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Hook for exception translation (used by JpaTransactionManager and JpaTemplate)
|
||||
// Hook for exception translation (used by JpaTransactionManager)
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -121,21 +116,4 @@ public class DefaultJpaDialect implements JpaDialect, Serializable {
|
|||
return EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
|
||||
public boolean supportsEntityManagerFactoryPlusOperations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsEntityManagerPlusOperations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public EntityManagerFactoryPlusOperations getEntityManagerFactoryPlusOperations(EntityManagerFactory rawEntityManager) {
|
||||
throw new UnsupportedOperationException(getClass().getName() + " does not support EntityManagerFactoryPlusOperations");
|
||||
}
|
||||
|
||||
public EntityManagerPlusOperations getEntityManagerPlusOperations(EntityManager rawEntityManager) {
|
||||
throw new UnsupportedOperationException(getClass().getName() + " does not support EntityManagerPlusOperations");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
|
@ -36,11 +36,8 @@ import org.springframework.util.CollectionUtils;
|
|||
* Base class for any class that needs to access an EntityManagerFactory,
|
||||
* usually in order to obtain an EntityManager. Defines common properties.
|
||||
*
|
||||
* <p>Not intended to be used directly. See {@link JpaAccessor}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see JpaAccessor
|
||||
* @see EntityManagerFactoryUtils
|
||||
*/
|
||||
public abstract class EntityManagerFactoryAccessor implements BeanFactoryAware {
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2006 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
/**
|
||||
* Extension of the standard JPA EntityManagerFactory interface, linking in
|
||||
* Spring's EntityManagerFactoryPlusOperations interface which defines
|
||||
* additional operations (beyond JPA 1.0) in a vendor-independent fashion.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see javax.persistence.EntityManager
|
||||
*/
|
||||
public interface EntityManagerFactoryPlus extends EntityManagerFactory, EntityManagerFactoryPlusOperations {
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2006 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
/**
|
||||
* Interface that defines common operations beyond the standard
|
||||
* JPA EntityManagerFactory interface, in a vendor-independent fashion.
|
||||
* To be adapted to specific JPA providers through a JpaDialect.
|
||||
*
|
||||
* <p>As of Spring 2.0, this interface does not define any operations yet.
|
||||
* The pass-through mechanism to the underlying JpaDialect is already in
|
||||
* place. Concrete operations may be added in future releases.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see JpaDialect#getEntityManagerPlusOperations
|
||||
* @see javax.persistence.EntityManagerFactory
|
||||
*/
|
||||
public interface EntityManagerFactoryPlusOperations {
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2006 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* Extension of the standard JPA EntityManager interface, linking in
|
||||
* Spring's EntityManagerPlusOperations interface which defines additional
|
||||
* operations (beyond JPA 1.0) in a vendor-independent fashion.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see javax.persistence.EntityManager
|
||||
*/
|
||||
public interface EntityManagerPlus extends EntityManager, EntityManagerPlusOperations {
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2006 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
/**
|
||||
* Interface that defines common operations beyond the standard
|
||||
* JPA EntityManager interface, in a vendor-independent fashion.
|
||||
* To be adapted to specific JPA providers through a JpaDialect.
|
||||
*
|
||||
* <p>As of Spring 2.0, this interface does not define any operations yet.
|
||||
* The pass-through mechanism to the underlying JpaDialect is already in
|
||||
* place. Concrete operations may be added in future releases.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see JpaDialect#getEntityManagerPlusOperations
|
||||
* @see javax.persistence.EntityManager
|
||||
*/
|
||||
public interface EntityManagerPlusOperations {
|
||||
|
||||
}
|
|
@ -59,48 +59,11 @@ import org.springframework.util.CollectionUtils;
|
|||
public abstract class ExtendedEntityManagerCreator {
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the
|
||||
* {@code joinTransaction()} method, but is not automatically
|
||||
* managed by the container.
|
||||
* Create an EntityManager that can join transactions with the {@code joinTransaction()}
|
||||
* method, but is not automatically managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* @param plusOperations an implementation of the EntityManagerPlusOperations
|
||||
* interface, if those operations should be exposed (may be {@code null})
|
||||
* @return an application-managed EntityManager that can join transactions
|
||||
* but does not participate in them automatically
|
||||
*/
|
||||
public static EntityManager createApplicationManagedEntityManager(
|
||||
EntityManager rawEntityManager, EntityManagerPlusOperations plusOperations) {
|
||||
|
||||
return createProxy(rawEntityManager, null, null, plusOperations, null, null, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the
|
||||
* {@code joinTransaction()} method, but is not automatically
|
||||
* managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* @param plusOperations an implementation of the EntityManagerPlusOperations
|
||||
* interface, if those operations should be exposed (may be {@code null})
|
||||
* @param exceptionTranslator the exception translator to use for translating
|
||||
* JPA commit/rollback exceptions during transaction synchronization
|
||||
* (may be {@code null})
|
||||
* @return an application-managed EntityManager that can join transactions
|
||||
* but does not participate in them automatically
|
||||
*/
|
||||
public static EntityManager createApplicationManagedEntityManager(
|
||||
EntityManager rawEntityManager, EntityManagerPlusOperations plusOperations,
|
||||
PersistenceExceptionTranslator exceptionTranslator) {
|
||||
|
||||
return createProxy(rawEntityManager, null, null, plusOperations, exceptionTranslator, null, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the
|
||||
* {@code joinTransaction()} method, but is not automatically
|
||||
* managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the
|
||||
* EntityManagerPlusOperations and PersistenceUnitInfo from
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @return an application-managed EntityManager that can join transactions
|
||||
* but does not participate in them automatically
|
||||
*/
|
||||
|
@ -111,12 +74,11 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an EntityManager that can join transactions with the
|
||||
* {@code joinTransaction()} method, but is not automatically
|
||||
* managed by the container.
|
||||
* Create an EntityManager that can join transactions with the {@code joinTransaction()}
|
||||
* method, but is not automatically managed by the container.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the
|
||||
* EntityManagerPlusOperations and PersistenceUnitInfo from
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||
* transactions (according to the JPA 2.1 SynchronizationType rules)
|
||||
* @return an application-managed EntityManager that can join transactions
|
||||
|
@ -128,47 +90,12 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
return createProxy(rawEntityManager, emfInfo, false, synchronizedWithTransaction);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param plusOperations an implementation of the EntityManagerPlusOperations
|
||||
* interface, if those operations should be exposed (may be {@code null})
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
* in any managed transaction
|
||||
*/
|
||||
public static EntityManager createContainerManagedEntityManager(
|
||||
EntityManager rawEntityManager, EntityManagerPlusOperations plusOperations) {
|
||||
|
||||
return createProxy(rawEntityManager, null, null, plusOperations, null, null, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param plusOperations an implementation of the EntityManagerPlusOperations
|
||||
* interface, if those operations should be exposed (may be {@code null})
|
||||
* @param exceptionTranslator the exception translator to use for translating
|
||||
* JPA commit/rollback exceptions during transaction synchronization
|
||||
* (may be {@code null})
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
* in any managed transaction
|
||||
*/
|
||||
public static EntityManager createContainerManagedEntityManager(
|
||||
EntityManager rawEntityManager, EntityManagerPlusOperations plusOperations,
|
||||
PersistenceExceptionTranslator exceptionTranslator) {
|
||||
|
||||
return createProxy(rawEntityManager, null, null, plusOperations, exceptionTranslator, null, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the
|
||||
* EntityManagerPlusOperations and PersistenceUnitInfo from
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
* in any managed transaction
|
||||
*/
|
||||
|
@ -182,9 +109,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 emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, appropriate handling
|
||||
* of the native EntityManagerFactory and available EntityManagerPlusOperations
|
||||
* will automatically apply.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
* in any managed transaction
|
||||
* @see javax.persistence.EntityManagerFactory#createEntityManager()
|
||||
|
@ -197,9 +123,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 emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, appropriate handling
|
||||
* of the native EntityManagerFactory and available EntityManagerPlusOperations
|
||||
* will automatically apply.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||
* call (may be {@code null})
|
||||
* @return a container-managed EntityManager that will automatically participate
|
||||
|
@ -214,9 +139,8 @@ 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.
|
||||
* @param emf the EntityManagerFactory to create the EntityManager with.
|
||||
* If this implements the EntityManagerFactoryInfo interface, appropriate handling
|
||||
* of the native EntityManagerFactory and available EntityManagerPlusOperations
|
||||
* will automatically apply.
|
||||
* If this implements the EntityManagerFactoryInfo interface, the corresponding
|
||||
* JpaDialect and PersistenceUnitInfo will be detected accordingly.
|
||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||
* call (may be {@code null})
|
||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||
|
@ -239,7 +163,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
else {
|
||||
EntityManager rawEntityManager = (!CollectionUtils.isEmpty(properties) ?
|
||||
emf.createEntityManager(properties) : emf.createEntityManager());
|
||||
return createProxy(rawEntityManager, null, null, null, null, null, true, synchronizedWithTransaction);
|
||||
return createProxy(rawEntityManager, null, null, null, null, true, synchronizedWithTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,8 +171,8 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
/**
|
||||
* Actually create the EntityManager proxy.
|
||||
* @param rawEntityManager raw EntityManager
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the
|
||||
* EntityManagerPlusOperations and PersistenceUnitInfo from
|
||||
* @param emfInfo the EntityManagerFactoryInfo to obtain the JpaDialect
|
||||
* and PersistenceUnitInfo from
|
||||
* @param containerManaged whether to follow container-managed EntityManager
|
||||
* or application-managed EntityManager semantics
|
||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||
|
@ -260,14 +184,10 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
|
||||
Assert.notNull(emfInfo, "EntityManagerFactoryInfo must not be null");
|
||||
JpaDialect jpaDialect = emfInfo.getJpaDialect();
|
||||
EntityManagerPlusOperations plusOperations = null;
|
||||
if (jpaDialect != null && jpaDialect.supportsEntityManagerPlusOperations()) {
|
||||
plusOperations = jpaDialect.getEntityManagerPlusOperations(rawEntityManager);
|
||||
}
|
||||
PersistenceUnitInfo pui = emfInfo.getPersistenceUnitInfo();
|
||||
Boolean jta = (pui != null ? pui.getTransactionType() == PersistenceUnitTransactionType.JTA : null);
|
||||
return createProxy(rawEntityManager, emfInfo.getEntityManagerInterface(),
|
||||
emfInfo.getBeanClassLoader(), plusOperations, jpaDialect, jta, containerManaged, synchronizedWithTransaction);
|
||||
emfInfo.getBeanClassLoader(), jpaDialect, jta, containerManaged, synchronizedWithTransaction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,8 +195,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
* @param rawEm raw EntityManager
|
||||
* @param emIfc the (potentially vendor-specific) EntityManager
|
||||
* interface to proxy, or {@code null} for default detection of all interfaces
|
||||
* @param plusOperations an implementation of the EntityManagerPlusOperations
|
||||
* interface, if those operations should be exposed (may be {@code null})
|
||||
* @param cl the ClassLoader to use for proxy creation (maybe {@code null})
|
||||
* @param exceptionTranslator the PersistenceException translator to use
|
||||
* @param jta whether to create a JTA-aware EntityManager
|
||||
* (or {@code null} if not known in advance)
|
||||
|
@ -288,8 +207,8 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
*/
|
||||
private static EntityManager createProxy(
|
||||
EntityManager rawEm, Class<? extends EntityManager> emIfc, ClassLoader cl,
|
||||
EntityManagerPlusOperations plusOperations, PersistenceExceptionTranslator exceptionTranslator,
|
||||
Boolean jta, boolean containerManaged, boolean synchronizedWithTransaction) {
|
||||
PersistenceExceptionTranslator exceptionTranslator, Boolean jta,
|
||||
boolean containerManaged, boolean synchronizedWithTransaction) {
|
||||
|
||||
Assert.notNull(rawEm, "EntityManager must not be null");
|
||||
Set<Class> ifcs = new LinkedHashSet<Class>();
|
||||
|
@ -300,14 +219,11 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
ifcs.addAll(ClassUtils.getAllInterfacesForClassAsSet(rawEm.getClass(), cl));
|
||||
}
|
||||
ifcs.add(EntityManagerProxy.class);
|
||||
if (plusOperations != null) {
|
||||
ifcs.add(EntityManagerPlusOperations.class);
|
||||
}
|
||||
return (EntityManager) Proxy.newProxyInstance(
|
||||
(cl != null ? cl : ExtendedEntityManagerCreator.class.getClassLoader()),
|
||||
ifcs.toArray(new Class[ifcs.size()]),
|
||||
new ExtendedEntityManagerInvocationHandler(
|
||||
rawEm, plusOperations, exceptionTranslator, jta, containerManaged, synchronizedWithTransaction));
|
||||
rawEm, exceptionTranslator, jta, containerManaged, synchronizedWithTransaction));
|
||||
}
|
||||
|
||||
|
||||
|
@ -321,8 +237,6 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
|
||||
private final EntityManager target;
|
||||
|
||||
private final EntityManagerPlusOperations plusOperations;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator;
|
||||
|
||||
private final boolean jta;
|
||||
|
@ -331,13 +245,11 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
|
||||
private final boolean synchronizedWithTransaction;
|
||||
|
||||
private ExtendedEntityManagerInvocationHandler(
|
||||
EntityManager target, EntityManagerPlusOperations plusOperations,
|
||||
private ExtendedEntityManagerInvocationHandler(EntityManager target,
|
||||
PersistenceExceptionTranslator exceptionTranslator, Boolean jta,
|
||||
boolean containerManaged, boolean synchronizedWithTransaction) {
|
||||
|
||||
this.target = target;
|
||||
this.plusOperations = plusOperations;
|
||||
this.exceptionTranslator = exceptionTranslator;
|
||||
this.jta = (jta != null ? jta : isJtaEntityManager());
|
||||
this.containerManaged = containerManaged;
|
||||
|
@ -418,12 +330,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
|
||||
// Invoke method on current EntityManager.
|
||||
try {
|
||||
if (method.getDeclaringClass().equals(EntityManagerPlusOperations.class)) {
|
||||
return method.invoke(this.plusOperations, args);
|
||||
}
|
||||
else {
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.support.DataAccessUtils;
|
||||
|
||||
/**
|
||||
* Base class for JpaTemplate and JpaInterceptor, defining common
|
||||
* properties such as EntityManagerFactory and flushing behavior.
|
||||
*
|
||||
* <p>Not intended to be used directly.
|
||||
* See {@link JpaTemplate} and {@link JpaInterceptor}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #setEntityManagerFactory
|
||||
* @see #setEntityManager
|
||||
* @see #setJpaDialect
|
||||
* @see #setFlushEager
|
||||
* @see JpaTemplate
|
||||
* @see JpaInterceptor
|
||||
* @see JpaDialect
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext})
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class JpaAccessor extends EntityManagerFactoryAccessor implements InitializingBean {
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
private JpaDialect jpaDialect = new DefaultJpaDialect();
|
||||
|
||||
private boolean flushEager = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set the JPA EntityManager to use.
|
||||
*/
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JPA EntityManager to use.
|
||||
*/
|
||||
public EntityManager getEntityManager() {
|
||||
return entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JPA dialect to use for this accessor.
|
||||
* <p>The dialect object can be used to retrieve the underlying JDBC
|
||||
* connection, for example.
|
||||
*/
|
||||
public void setJpaDialect(JpaDialect jpaDialect) {
|
||||
this.jpaDialect = (jpaDialect != null ? jpaDialect : new DefaultJpaDialect());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JPA dialect to use for this accessor.
|
||||
* <p>Creates a default one for the specified EntityManagerFactory if none set.
|
||||
*/
|
||||
public JpaDialect getJpaDialect() {
|
||||
return this.jpaDialect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if this accessor should flush changes to the database eagerly.
|
||||
* <p>Eager flushing leads to immediate synchronization with the database,
|
||||
* even if in a transaction. This causes inconsistencies to show up and throw
|
||||
* a respective exception immediately, and JDBC access code that participates
|
||||
* in the same transaction will see the changes as the database is already
|
||||
* aware of them then. But the drawbacks are:
|
||||
* <ul>
|
||||
* <li>additional communication roundtrips with the database, instead of a
|
||||
* single batch at transaction commit;
|
||||
* <li>the fact that an actual database rollback is needed if the JPA
|
||||
* transaction rolls back (due to already submitted SQL statements).
|
||||
* </ul>
|
||||
*/
|
||||
public void setFlushEager(boolean flushEager) {
|
||||
this.flushEager = flushEager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if this accessor should flush changes to the database eagerly.
|
||||
*/
|
||||
public boolean isFlushEager() {
|
||||
return this.flushEager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly initialize the JPA dialect, creating a default one
|
||||
* for the specified EntityManagerFactory if none set.
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
EntityManagerFactory emf = getEntityManagerFactory();
|
||||
if (emf == null && getEntityManager() == null) {
|
||||
throw new IllegalArgumentException("'entityManagerFactory' or 'entityManager' is required");
|
||||
}
|
||||
if (emf instanceof EntityManagerFactoryInfo) {
|
||||
JpaDialect jpaDialect = ((EntityManagerFactoryInfo) emf).getJpaDialect();
|
||||
if (jpaDialect != null) {
|
||||
setJpaDialect(jpaDialect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flush the given JPA entity manager if necessary.
|
||||
* @param em the current JPA PersistenceManage
|
||||
* @param existingTransaction if executing within an existing transaction
|
||||
* @throws javax.persistence.PersistenceException in case of JPA flushing errors
|
||||
*/
|
||||
protected void flushIfNecessary(EntityManager em, boolean existingTransaction) throws PersistenceException {
|
||||
if (isFlushEager()) {
|
||||
logger.debug("Eagerly flushing JPA entity manager");
|
||||
em.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy if necessary, or
|
||||
* return the exception itself if it is not persistence related
|
||||
* <p>Default implementation delegates to the JpaDialect.
|
||||
* May be overridden in subclasses.
|
||||
* @param ex runtime exception that occured, which may or may not
|
||||
* be JPA-related
|
||||
* @return the corresponding DataAccessException instance if
|
||||
* wrapping should occur, otherwise the raw exception
|
||||
* @see org.springframework.dao.support.DataAccessUtils#translateIfNecessary
|
||||
*/
|
||||
public RuntimeException translateIfNecessary(RuntimeException ex) {
|
||||
return DataAccessUtils.translateIfNecessary(ex, getJpaDialect());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
* Callback interface for JPA code. To be used with {@link JpaTemplate}'s
|
||||
* execution method, often as anonymous classes within a method implementation.
|
||||
* A typical implementation will call {@code EntityManager.find/merge}
|
||||
* to perform some operations on persistent objects.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see JpaTemplate
|
||||
* @see JpaTransactionManager
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext})
|
||||
*/
|
||||
@Deprecated
|
||||
public interface JpaCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code JpaTemplate.execute} with an active
|
||||
* JPA {@code EntityManager}. Does not need to care about activating
|
||||
* or closing the {@code EntityManager}, or handling transactions.
|
||||
*
|
||||
* <p>Note that JPA callback code will not flush any modifications to the
|
||||
* database if not executed within a transaction. Thus, you need to make
|
||||
* sure that JpaTransactionManager has initiated a JPA transaction when
|
||||
* the callback gets called, at least if you want to write to the database.
|
||||
*
|
||||
* <p>Allows for returning a result object created within the callback,
|
||||
* i.e. a domain object or a collection of domain objects.
|
||||
* A thrown custom RuntimeException is treated as an application exception:
|
||||
* It gets propagated to the caller of the template.
|
||||
*
|
||||
* @param em active EntityManager
|
||||
* @return a result object, or {@code null} if none
|
||||
* @throws PersistenceException if thrown by the JPA API
|
||||
* @see JpaTemplate#execute
|
||||
* @see JpaTemplate#executeFind
|
||||
*/
|
||||
T doInJpa(EntityManager em) throws PersistenceException;
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
|
@ -18,7 +18,6 @@ package org.springframework.orm.jpa;
|
|||
|
||||
import java.sql.SQLException;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
|
@ -27,7 +26,7 @@ import org.springframework.transaction.TransactionDefinition;
|
|||
import org.springframework.transaction.TransactionException;
|
||||
|
||||
/**
|
||||
* SPI strategy that encapsulates certain functionality that standard JPA 1.0
|
||||
* SPI strategy that encapsulates certain functionality that standard JPA 2.0
|
||||
* does not offer, such as access to the underlying JDBC Connection. This
|
||||
* strategy is mainly intended for standalone usage of a JPA provider; most
|
||||
* of its functionality is not relevant when running with JTA transactions.
|
||||
|
@ -45,7 +44,6 @@ import org.springframework.transaction.TransactionException;
|
|||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see DefaultJpaDialect
|
||||
* @see JpaAccessor#setJpaDialect
|
||||
* @see JpaTransactionManager#setJpaDialect
|
||||
* @see JpaVendorAdapter#getJpaDialect()
|
||||
* @see AbstractEntityManagerFactoryBean#setJpaDialect
|
||||
|
@ -53,51 +51,6 @@ import org.springframework.transaction.TransactionException;
|
|||
*/
|
||||
public interface JpaDialect extends PersistenceExceptionTranslator {
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Hooks for non-standard persistence operations (used by EntityManagerFactory beans)
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return whether the EntityManagerFactoryPlus(Operations) interface is
|
||||
* supported by this provider.
|
||||
* @see EntityManagerFactoryPlusOperations
|
||||
* @see EntityManagerFactoryPlus
|
||||
*/
|
||||
boolean supportsEntityManagerFactoryPlusOperations();
|
||||
|
||||
/**
|
||||
* Return whether the EntityManagerPlus(Operations) interface is
|
||||
* supported by this provider.
|
||||
* @see EntityManagerPlusOperations
|
||||
* @see EntityManagerPlus
|
||||
*/
|
||||
boolean supportsEntityManagerPlusOperations();
|
||||
|
||||
/**
|
||||
* Return an EntityManagerFactoryPlusOperations implementation for
|
||||
* the given raw EntityManagerFactory. This operations object can be
|
||||
* used to serve the additional operations behind a proxy that
|
||||
* implements the EntityManagerFactoryPlus interface.
|
||||
* @param rawEntityManager the raw provider-specific EntityManagerFactory
|
||||
* @return the EntityManagerFactoryPlusOperations implementation
|
||||
*/
|
||||
EntityManagerFactoryPlusOperations getEntityManagerFactoryPlusOperations(EntityManagerFactory rawEntityManager);
|
||||
|
||||
/**
|
||||
* Return an EntityManagerPlusOperations implementation for
|
||||
* the given raw EntityManager. This operations object can be
|
||||
* used to serve the additional operations behind a proxy that
|
||||
* implements the EntityManagerPlus interface.
|
||||
* @param rawEntityManager the raw provider-specific EntityManagerFactory
|
||||
* @return the EntityManagerFactoryPlusOperations implementation
|
||||
*/
|
||||
EntityManagerPlusOperations getEntityManagerPlusOperations(EntityManager rawEntityManager);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Hooks for transaction management (used by JpaTransactionManager)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Begin the given JPA transaction, applying the semantics specified by the
|
||||
* given Spring transaction definition (in particular, an isolation level
|
||||
|
@ -173,7 +126,7 @@ public interface JpaDialect extends PersistenceExceptionTranslator {
|
|||
* needing access to the underlying JDBC Connection, usually within an active JPA
|
||||
* transaction (for example, by JpaTransactionManager). The returned handle will
|
||||
* be passed into the {@code releaseJdbcConnection} method when not needed anymore.
|
||||
* <p>This strategy is necessary as JPA 1.0 does not provide a standard way to retrieve
|
||||
* <p>This strategy is necessary as JPA does not provide a standard way to retrieve
|
||||
* the underlying JDBC Connection (due to the fact that a JPA implementation might not
|
||||
* work with a relational database at all).
|
||||
* <p>Implementations are encouraged to return an unwrapped Connection object, i.e.
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* This interceptor binds a new JPA EntityManager to the thread before a method
|
||||
* call, closing and removing it afterwards in case of any method outcome.
|
||||
* If there already is a pre-bound EntityManager (e.g. from JpaTransactionManager,
|
||||
* or from a surrounding JPA-intercepted method), the interceptor simply participates in it.
|
||||
*
|
||||
* <p>Application code must retrieve a JPA EntityManager via the
|
||||
* {@code EntityManagerFactoryUtils.getEntityManager} method or - preferably -
|
||||
* via a shared {@code EntityManager} reference, to be able to detect a
|
||||
* thread-bound EntityManager. Typically, the code will look like as follows:
|
||||
*
|
||||
* <pre>
|
||||
* public void doSomeDataAccessAction() {
|
||||
* this.entityManager...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Note that this interceptor automatically translates PersistenceExceptions,
|
||||
* via delegating to the {@code EntityManagerFactoryUtils.convertJpaAccessException}
|
||||
* method that converts them to exceptions that are compatible with the
|
||||
* {@code org.springframework.dao} exception hierarchy (like JpaTemplate does).
|
||||
*
|
||||
* <p>This class can be considered a declarative alternative to JpaTemplate's
|
||||
* callback approach. The advantages are:
|
||||
* <ul>
|
||||
* <li>no anonymous classes necessary for callback implementations;
|
||||
* <li>the possibility to throw any application exceptions from within data access code.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The drawback is the dependency on interceptor configuration. However, note
|
||||
* that this interceptor is usually <i>not</i> necessary in scenarios where the
|
||||
* data access code always executes within transactions. A transaction will always
|
||||
* have a thread-bound EntityManager in the first place, so adding this interceptor
|
||||
* to the configuration just adds value when fine-tuning EntityManager settings
|
||||
* like the flush mode - or when relying on exception translation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see JpaTransactionManager
|
||||
* @see JpaTemplate
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext}) and
|
||||
* AOP-driven exception translation through
|
||||
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}
|
||||
*/
|
||||
@Deprecated
|
||||
public class JpaInterceptor extends JpaAccessor implements MethodInterceptor {
|
||||
|
||||
private boolean exceptionConversionEnabled = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to convert any PersistenceException raised to a Spring DataAccessException,
|
||||
* compatible with the {@code org.springframework.dao} exception hierarchy.
|
||||
* <p>Default is "true". Turn this flag off to let the caller receive raw exceptions
|
||||
* as-is, without any wrapping.
|
||||
* @see org.springframework.dao.DataAccessException
|
||||
*/
|
||||
public void setExceptionConversionEnabled(boolean exceptionConversionEnabled) {
|
||||
this.exceptionConversionEnabled = exceptionConversionEnabled;
|
||||
}
|
||||
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
// Determine current EntityManager: either the transactional one
|
||||
// managed by the factory or a temporary one for the given invocation.
|
||||
EntityManager em = getTransactionalEntityManager();
|
||||
boolean isNewEm = false;
|
||||
if (em == null) {
|
||||
logger.debug("Creating new EntityManager for JpaInterceptor invocation");
|
||||
em = createEntityManager();
|
||||
isNewEm = true;
|
||||
TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), new EntityManagerHolder(em));
|
||||
}
|
||||
|
||||
try {
|
||||
Object retVal = methodInvocation.proceed();
|
||||
flushIfNecessary(em, !isNewEm);
|
||||
return retVal;
|
||||
}
|
||||
catch (RuntimeException rawException) {
|
||||
if (this.exceptionConversionEnabled) {
|
||||
// Translation enabled. Translate if we understand the exception.
|
||||
throw translateIfNecessary(rawException);
|
||||
}
|
||||
else {
|
||||
// Translation not enabled. Don't try to translate.
|
||||
throw rawException;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (isNewEm) {
|
||||
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
|
||||
EntityManagerFactoryUtils.closeEntityManager(em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of JPA operations,
|
||||
* implemented by {@link JpaTemplate}. Not often used, but a useful
|
||||
* option to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* <p>Defines {@code JpaTemplate}'s data access methods that mirror
|
||||
* various {@link javax.persistence.EntityManager} methods. Users are
|
||||
* strongly encouraged to read the JPA {@code EntityManager}
|
||||
* javadocs for details on the semantics of those methods.
|
||||
*
|
||||
* <p>Note that lazy loading will just work with an open JPA
|
||||
* {@code EntityManager}, either within a managed transaction or within
|
||||
* {@link org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter}/
|
||||
* {@link org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor}.
|
||||
* Furthermore, some operations just make sense within transactions,
|
||||
* for example: {@code flush}, {@code clear}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see JpaTemplate
|
||||
* @see javax.persistence.EntityManager
|
||||
* @see JpaTransactionManager
|
||||
* @see JpaDialect
|
||||
* @see org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
|
||||
* @see org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext}).
|
||||
* Note that this interface did not get upgraded to JPA 2.0 and never will.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface JpaOperations {
|
||||
|
||||
<T> T execute(JpaCallback<T> action) throws DataAccessException;
|
||||
|
||||
List executeFind(JpaCallback<?> action) throws DataAccessException;
|
||||
|
||||
<T> T find(Class<T> entityClass, Object id) throws DataAccessException;
|
||||
|
||||
<T> T getReference(Class<T> entityClass, Object id) throws DataAccessException;
|
||||
|
||||
boolean contains(Object entity) throws DataAccessException;
|
||||
|
||||
void refresh(Object entity) throws DataAccessException;
|
||||
|
||||
void persist(Object entity) throws DataAccessException;
|
||||
|
||||
<T> T merge(T entity) throws DataAccessException;
|
||||
|
||||
void remove(Object entity) throws DataAccessException;
|
||||
|
||||
void flush() throws DataAccessException;
|
||||
|
||||
List find(String queryString) throws DataAccessException;
|
||||
|
||||
List find(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
List findByNamedParams(String queryString, Map<String, ?> params) throws DataAccessException;
|
||||
|
||||
List findByNamedQuery(String queryName) throws DataAccessException;
|
||||
|
||||
List findByNamedQuery(String queryName, Object... values) throws DataAccessException;
|
||||
|
||||
List findByNamedQueryAndNamedParams(String queryName, Map<String, ?> params) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -1,442 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Helper class that allows for writing JPA data access code in the same style
|
||||
* as with Spring's well-known JdoTemplate and HibernateTemplate classes.
|
||||
* Automatically converts PersistenceExceptions into Spring DataAccessExceptions,
|
||||
* following the {@code org.springframework.dao} exception hierarchy.
|
||||
*
|
||||
* <p>The central method is of this template is "execute", supporting JPA access code
|
||||
* implementing the {@link JpaCallback} interface. It provides JPA EntityManager
|
||||
* handling such that neither the JpaCallback implementation nor the calling code
|
||||
* needs to explicitly care about retrieving/closing EntityManagers, or handling
|
||||
* JPA lifecycle exceptions.
|
||||
*
|
||||
* <p>Can be used within a service implementation via direct instantiation with
|
||||
* a EntityManagerFactory reference, or get prepared in an application context
|
||||
* and given to services as bean reference. Note: The EntityManagerFactory should
|
||||
* always be configured as bean in the application context, in the first case
|
||||
* given to the service directly, in the second case to the prepared template.
|
||||
*
|
||||
* <p><b>NOTE: JpaTemplate mainly exists as a sibling of JdoTemplate and
|
||||
* HibernateTemplate, offering the same style for people used to it. For newly
|
||||
* started projects, consider adopting the standard JPA style of coding data
|
||||
* access objects instead, based on a "shared EntityManager" reference injected
|
||||
* via a Spring bean definition or the JPA PersistenceContext annotation.</b>
|
||||
* (Using Spring's SharedEntityManagerBean / PersistenceAnnotationBeanPostProcessor,
|
||||
* or using a direct JNDI lookup for an EntityManager on a Java EE 5 server.)
|
||||
*
|
||||
* <p>JpaTemplate can be considered as direct alternative to working with the
|
||||
* native JPA EntityManager API (through a shared EntityManager reference,
|
||||
* as outlined above). The major advantage is its automatic conversion to
|
||||
* DataAccessExceptions; the major disadvantage is that it introduces
|
||||
* another thin layer on top of the native JPA API. Note that exception
|
||||
* translation can also be achieved through AOP advice; check out
|
||||
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}.
|
||||
*
|
||||
* <p>{@link LocalContainerEntityManagerFactoryBean} is the preferred way of
|
||||
* obtaining a reference to an EntityManagerFactory, at least outside of a full
|
||||
* Java EE 5 environment. The Spring application context will manage its lifecycle,
|
||||
* initializing and shutting down the factory as part of the application.
|
||||
* Within a Java EE 5 environment, you will typically work with a server-managed
|
||||
* EntityManagerFactory that is exposed via JNDI, obtained through Spring's
|
||||
* {@link org.springframework.jndi.JndiObjectFactoryBean}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #setEntityManagerFactory
|
||||
* @see JpaCallback
|
||||
* @see javax.persistence.EntityManager
|
||||
* @see LocalEntityManagerFactoryBean
|
||||
* @see LocalContainerEntityManagerFactoryBean
|
||||
* @see JpaTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
|
||||
* @see org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext})
|
||||
* Note that this class did not get upgraded to JPA 2.0 and never will.
|
||||
*/
|
||||
@Deprecated
|
||||
public class JpaTemplate extends JpaAccessor implements JpaOperations {
|
||||
|
||||
private boolean exposeNativeEntityManager = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new JpaTemplate instance.
|
||||
*/
|
||||
public JpaTemplate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JpaTemplate instance.
|
||||
* @param emf EntityManagerFactory to create EntityManagers
|
||||
*/
|
||||
public JpaTemplate(EntityManagerFactory emf) {
|
||||
setEntityManagerFactory(emf);
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JpaTemplate instance.
|
||||
* @param em EntityManager to use
|
||||
*/
|
||||
public JpaTemplate(EntityManager em) {
|
||||
setEntityManager(em);
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to expose the native JPA EntityManager to JpaCallback
|
||||
* code. Default is "false": a EntityManager proxy will be returned,
|
||||
* suppressing {@code close} calls and automatically applying transaction
|
||||
* timeouts (if any).
|
||||
* <p>As there is often a need to cast to a provider-specific EntityManager
|
||||
* class in DAOs that use the JPA 1.0 API, for JPA 2.0 previews and other
|
||||
* provider-specific functionality, the exposed proxy implements all interfaces
|
||||
* implemented by the original EntityManager. If this is not sufficient,
|
||||
* turn this flag to "true".
|
||||
* @see JpaCallback
|
||||
* @see javax.persistence.EntityManager
|
||||
*/
|
||||
public void setExposeNativeEntityManager(boolean exposeNativeEntityManager) {
|
||||
this.exposeNativeEntityManager = exposeNativeEntityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to expose the native JPA EntityManager to JpaCallback
|
||||
* code, or rather an EntityManager proxy.
|
||||
*/
|
||||
public boolean isExposeNativeEntityManager() {
|
||||
return this.exposeNativeEntityManager;
|
||||
}
|
||||
|
||||
|
||||
public <T> T execute(JpaCallback<T> action) throws DataAccessException {
|
||||
return execute(action, isExposeNativeEntityManager());
|
||||
}
|
||||
|
||||
public List executeFind(JpaCallback<?> action) throws DataAccessException {
|
||||
Object result = execute(action, isExposeNativeEntityManager());
|
||||
if (!(result instanceof List)) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Result object returned from JpaCallback isn't a List: [" + result + "]");
|
||||
}
|
||||
return (List) result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* EntityManager.
|
||||
* @param action callback object that specifies the JPA action
|
||||
* @param exposeNativeEntityManager whether to expose the native
|
||||
* JPA entity manager to callback code
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @throws org.springframework.dao.DataAccessException in case of JPA errors
|
||||
*/
|
||||
public <T> T execute(JpaCallback<T> action, boolean exposeNativeEntityManager) throws DataAccessException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
|
||||
EntityManager em = getEntityManager();
|
||||
boolean isNewEm = false;
|
||||
if (em == null) {
|
||||
em = getTransactionalEntityManager();
|
||||
if (em == null) {
|
||||
logger.debug("Creating new EntityManager for JpaTemplate execution");
|
||||
em = createEntityManager();
|
||||
isNewEm = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
EntityManager emToExpose = (exposeNativeEntityManager ? em : createEntityManagerProxy(em));
|
||||
T result = action.doInJpa(emToExpose);
|
||||
flushIfNecessary(em, !isNewEm);
|
||||
return result;
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw translateIfNecessary(ex);
|
||||
}
|
||||
finally {
|
||||
if (isNewEm) {
|
||||
logger.debug("Closing new EntityManager after JPA template execution");
|
||||
EntityManagerFactoryUtils.closeEntityManager(em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a close-suppressing proxy for the given JPA EntityManager.
|
||||
* The proxy also prepares returned JPA Query objects.
|
||||
* @param em the JPA EntityManager to create a proxy for
|
||||
* @return the EntityManager proxy, implementing all interfaces
|
||||
* implemented by the passed-in EntityManager object (that is,
|
||||
* also implementing all provider-specific extension interfaces)
|
||||
* @see javax.persistence.EntityManager#close
|
||||
*/
|
||||
protected EntityManager createEntityManagerProxy(EntityManager em) {
|
||||
Class[] ifcs = null;
|
||||
EntityManagerFactory emf = getEntityManagerFactory();
|
||||
if (emf instanceof EntityManagerFactoryInfo) {
|
||||
Class entityManagerInterface = ((EntityManagerFactoryInfo) emf).getEntityManagerInterface();
|
||||
if (entityManagerInterface != null) {
|
||||
ifcs = new Class[] {entityManagerInterface};
|
||||
}
|
||||
}
|
||||
if (ifcs == null) {
|
||||
ifcs = ClassUtils.getAllInterfacesForClass(em.getClass());
|
||||
}
|
||||
return (EntityManager) Proxy.newProxyInstance(
|
||||
em.getClass().getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(em));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for load, save, delete
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public <T> T find(final Class<T> entityClass, final Object id) throws DataAccessException {
|
||||
return execute(new JpaCallback<T>() {
|
||||
public T doInJpa(EntityManager em) throws PersistenceException {
|
||||
return em.find(entityClass, id);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public <T> T getReference(final Class<T> entityClass, final Object id) throws DataAccessException {
|
||||
return execute(new JpaCallback<T>() {
|
||||
public T doInJpa(EntityManager em) throws PersistenceException {
|
||||
return em.getReference(entityClass, id);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public boolean contains(final Object entity) throws DataAccessException {
|
||||
return execute(new JpaCallback<Boolean>() {
|
||||
public Boolean doInJpa(EntityManager em) throws PersistenceException {
|
||||
return em.contains(entity);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public void refresh(final Object entity) throws DataAccessException {
|
||||
execute(new JpaCallback<Object>() {
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
em.refresh(entity);
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public void persist(final Object entity) throws DataAccessException {
|
||||
execute(new JpaCallback<Object>() {
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
em.persist(entity);
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public <T> T merge(final T entity) throws DataAccessException {
|
||||
return execute(new JpaCallback<T>() {
|
||||
public T doInJpa(EntityManager em) throws PersistenceException {
|
||||
return em.merge(entity);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public void remove(final Object entity) throws DataAccessException {
|
||||
execute(new JpaCallback<Object>() {
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
em.remove(entity);
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
public void flush() throws DataAccessException {
|
||||
execute(new JpaCallback<Object>() {
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
em.flush();
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public List find(String queryString) throws DataAccessException {
|
||||
return find(queryString, (Object[]) null);
|
||||
}
|
||||
|
||||
public List find(final String queryString, final Object... values) throws DataAccessException {
|
||||
return execute(new JpaCallback<List>() {
|
||||
public List doInJpa(EntityManager em) throws PersistenceException {
|
||||
Query queryObject = em.createQuery(queryString);
|
||||
prepareQuery(queryObject);
|
||||
if (values != null) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
queryObject.setParameter(i + 1, values[i]);
|
||||
}
|
||||
}
|
||||
return queryObject.getResultList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List findByNamedParams(final String queryString, final Map<String, ?> params) throws DataAccessException {
|
||||
return execute(new JpaCallback<List>() {
|
||||
public List doInJpa(EntityManager em) throws PersistenceException {
|
||||
Query queryObject = em.createQuery(queryString);
|
||||
prepareQuery(queryObject);
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, ?> entry : params.entrySet()) {
|
||||
queryObject.setParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return queryObject.getResultList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List findByNamedQuery(String queryName) throws DataAccessException {
|
||||
return findByNamedQuery(queryName, (Object[]) null);
|
||||
}
|
||||
|
||||
public List findByNamedQuery(final String queryName, final Object... values) throws DataAccessException {
|
||||
return execute(new JpaCallback<List>() {
|
||||
public List doInJpa(EntityManager em) throws PersistenceException {
|
||||
Query queryObject = em.createNamedQuery(queryName);
|
||||
prepareQuery(queryObject);
|
||||
if (values != null) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
queryObject.setParameter(i + 1, values[i]);
|
||||
}
|
||||
}
|
||||
return queryObject.getResultList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List findByNamedQueryAndNamedParams(final String queryName, final Map<String, ?> params)
|
||||
throws DataAccessException {
|
||||
|
||||
return execute(new JpaCallback<List>() {
|
||||
public List doInJpa(EntityManager em) throws PersistenceException {
|
||||
Query queryObject = em.createNamedQuery(queryName);
|
||||
prepareQuery(queryObject);
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, ?> entry : params.entrySet()) {
|
||||
queryObject.setParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return queryObject.getResultList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the given JPA query object. To be used within a JpaCallback.
|
||||
* <p>Applies a transaction timeout, if any. If you don't use such timeouts,
|
||||
* the call is a no-op.
|
||||
* <p>In general, prefer a proxied EntityManager instead, which will
|
||||
* automatically apply the transaction timeout (through the use of a special
|
||||
* EntityManager proxy). You need to set the "exposeNativeEntityManager"
|
||||
* property to "false" to activate this. Note that you won't be able to cast
|
||||
* to a provider-specific JPA EntityManager class anymore then.
|
||||
* @param query the JPA query object
|
||||
* @see JpaCallback#doInJpa
|
||||
* @see EntityManagerFactoryUtils#applyTransactionTimeout
|
||||
* @see #setExposeNativeEntityManager
|
||||
*/
|
||||
public void prepareQuery(Query query) {
|
||||
EntityManagerFactory emf = getEntityManagerFactory();
|
||||
if (emf != null) {
|
||||
EntityManagerFactoryUtils.applyTransactionTimeout(query, getEntityManagerFactory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that suppresses close calls on JPA EntityManagers.
|
||||
* Also prepares returned Query objects.
|
||||
* @see javax.persistence.EntityManager#close()
|
||||
*/
|
||||
private class CloseSuppressingInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final EntityManager target;
|
||||
|
||||
public CloseSuppressingInvocationHandler(EntityManager target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Invocation on EntityManager interface (or provider-specific extension) 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 System.identityHashCode(proxy);
|
||||
}
|
||||
else if (method.getName().equals("close")) {
|
||||
// Handle close method: suppress, not valid.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Invoke method on target EntityManager.
|
||||
try {
|
||||
Object retVal = method.invoke(this.target, args);
|
||||
// If return value is a JPA Query object, apply transaction timeout.
|
||||
if (retVal instanceof Query) {
|
||||
prepareQuery(((Query) retVal));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -55,8 +55,8 @@ import org.springframework.util.CollectionUtils;
|
|||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation
|
||||
* for a single JPA {@link javax.persistence.EntityManagerFactory}. Binds a JPA
|
||||
* EntityManager from the specified factory to the thread, potentially allowing for
|
||||
* one thread-bound EntityManager per factory. {@link SharedEntityManagerCreator}
|
||||
* and {@link JpaTemplate} are aware of thread-bound entity managers and participate
|
||||
* one thread-bound EntityManager per factory. {@link SharedEntityManagerCreator} and
|
||||
* {@code @PersistenceContext} are aware of thread-bound entity managers and participate
|
||||
* in such transactions automatically. Using either is required for JPA access code
|
||||
* supporting this transaction management mechanism.
|
||||
*
|
||||
|
@ -100,7 +100,6 @@ import org.springframework.util.CollectionUtils;
|
|||
* @see #setEntityManagerFactory
|
||||
* @see #setDataSource
|
||||
* @see LocalEntityManagerFactoryBean
|
||||
* @see JpaTemplate#execute
|
||||
* @see org.springframework.orm.jpa.support.SharedEntityManagerBean
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
|
|
|
@ -65,6 +65,8 @@ import org.springframework.util.ClassUtils;
|
|||
* plus the {@link EntityManagerFactoryInfo} interface which exposes additional
|
||||
* metadata as assembled by this FactoryBean.
|
||||
*
|
||||
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
|
@ -52,12 +52,13 @@ import javax.persistence.spi.PersistenceProvider;
|
|||
* to the JPA provider, consider using Spring's more powerful
|
||||
* {@link LocalContainerEntityManagerFactoryBean} instead.
|
||||
*
|
||||
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
* @see #setJpaProperties
|
||||
* @see #setJpaVendorAdapter
|
||||
* @see JpaTemplate#setEntityManagerFactory
|
||||
* @see JpaTransactionManager#setEntityManagerFactory
|
||||
* @see LocalContainerEntityManagerFactoryBean
|
||||
* @see org.springframework.jndi.JndiObjectFactoryBean
|
||||
|
|
|
@ -56,9 +56,6 @@ public abstract class SharedEntityManagerCreator {
|
|||
* Create a transactional EntityManager proxy for the given EntityManagerFactory,
|
||||
* automatically joining ongoing transactions.
|
||||
* @param emf the EntityManagerFactory to delegate to.
|
||||
* If this implements the {@link EntityManagerFactoryInfo} interface,
|
||||
* appropriate handling of the native EntityManagerFactory and available
|
||||
* {@link EntityManagerPlusOperations} will automatically apply.
|
||||
* @return a shareable transaction EntityManager proxy
|
||||
*/
|
||||
public static EntityManager createSharedEntityManager(EntityManagerFactory emf) {
|
||||
|
@ -68,9 +65,6 @@ public abstract class SharedEntityManagerCreator {
|
|||
/**
|
||||
* Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
||||
* @param emf the EntityManagerFactory to delegate to.
|
||||
* If this implements the {@link EntityManagerFactoryInfo} interface,
|
||||
* appropriate handling of the native EntityManagerFactory and available
|
||||
* {@link EntityManagerPlusOperations} will automatically apply.
|
||||
* @param properties the properties to be passed into the
|
||||
* {@code createEntityManager} call (may be {@code null})
|
||||
* @return a shareable transaction EntityManager proxy
|
||||
|
@ -82,9 +76,6 @@ public abstract class SharedEntityManagerCreator {
|
|||
/**
|
||||
* Create a transactional EntityManager proxy for the given EntityManagerFactory.
|
||||
* @param emf the EntityManagerFactory to delegate to.
|
||||
* If this implements the {@link EntityManagerFactoryInfo} interface,
|
||||
* appropriate handling of the native EntityManagerFactory and available
|
||||
* {@link EntityManagerPlusOperations} will automatically apply.
|
||||
* @param properties the properties to be passed into the
|
||||
* {@code createEntityManager} call (may be {@code null})
|
||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||
|
@ -94,25 +85,9 @@ public abstract class SharedEntityManagerCreator {
|
|||
public static EntityManager createSharedEntityManager(
|
||||
EntityManagerFactory emf, Map properties, boolean synchronizedWithTransaction) {
|
||||
|
||||
Class[] emIfcs;
|
||||
if (emf instanceof EntityManagerFactoryInfo) {
|
||||
EntityManagerFactoryInfo emfInfo = (EntityManagerFactoryInfo) emf;
|
||||
Class emIfc = emfInfo.getEntityManagerInterface();
|
||||
if (emIfc == null) {
|
||||
emIfc = EntityManager.class;
|
||||
}
|
||||
JpaDialect jpaDialect = emfInfo.getJpaDialect();
|
||||
if (jpaDialect != null && jpaDialect.supportsEntityManagerPlusOperations()) {
|
||||
emIfcs = new Class[] {emIfc, EntityManagerPlus.class};
|
||||
}
|
||||
else {
|
||||
emIfcs = new Class[] {emIfc};
|
||||
}
|
||||
}
|
||||
else {
|
||||
emIfcs = new Class[] {EntityManager.class};
|
||||
}
|
||||
return createSharedEntityManager(emf, properties, synchronizedWithTransaction, emIfcs);
|
||||
Class emIfc = (emf instanceof EntityManagerFactoryInfo ?
|
||||
((EntityManagerFactoryInfo) emf).getEntityManagerInterface() : EntityManager.class);
|
||||
return createSharedEntityManager(emf, properties, synchronizedWithTransaction, emIfc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa.support;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.springframework.dao.support.DaoSupport;
|
||||
import org.springframework.orm.jpa.JpaTemplate;
|
||||
|
||||
/**
|
||||
* Convenient super class for JPA data access objects. Intended for
|
||||
* JpaTemplate usage. Alternatively, JPA-based DAOs can be coded
|
||||
* against the plain JPA EntityManagerFactory/EntityManager API.
|
||||
*
|
||||
* <p>Requires an EntityManagerFactory or EntityManager to be set,
|
||||
* providing a JpaTemplate based on it to subclasses. Can alternatively
|
||||
* be initialized directly via a JpaTemplate, to reuse the latter's
|
||||
* settings such as the EntityManagerFactory, JpaDialect, flush mode, etc.
|
||||
*
|
||||
* <p>This class will create its own JpaTemplate if an EntityManagerFactory
|
||||
* or EntityManager reference is passed in. A custom JpaTemplate instance
|
||||
* can be used through overriding {@code createJpaTemplate}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #setEntityManagerFactory
|
||||
* @see #setEntityManager
|
||||
* @see #createJpaTemplate
|
||||
* @see #setJpaTemplate
|
||||
* @see org.springframework.orm.jpa.JpaTemplate
|
||||
* @deprecated as of Spring 3.1, in favor of native EntityManager usage
|
||||
* (typically obtained through {@code @PersistenceContext})
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class JpaDaoSupport extends DaoSupport {
|
||||
|
||||
private JpaTemplate jpaTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Set the JPA EntityManagerFactory to be used by this DAO.
|
||||
* Will automatically create a JpaTemplate for the given EntityManagerFactory.
|
||||
* @see #createJpaTemplate
|
||||
* @see #setJpaTemplate
|
||||
*/
|
||||
public final void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
if (this.jpaTemplate == null || entityManagerFactory != this.jpaTemplate.getEntityManagerFactory()) {
|
||||
this.jpaTemplate = createJpaTemplate(entityManagerFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JpaTemplate for the given EntityManagerFactory.
|
||||
* Only invoked if populating the DAO with a EntityManagerFactory reference!
|
||||
* <p>Can be overridden in subclasses to provide a JpaTemplate instance
|
||||
* with different configuration, or a custom JpaTemplate subclass.
|
||||
* @param entityManagerFactory the JPA EntityManagerFactory to create a JpaTemplate for
|
||||
* @return the new JpaTemplate instance
|
||||
* @see #setEntityManagerFactory
|
||||
*/
|
||||
protected JpaTemplate createJpaTemplate(EntityManagerFactory entityManagerFactory) {
|
||||
return new JpaTemplate(entityManagerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JPA EntityManager to be used by this DAO.
|
||||
* Will automatically create a JpaTemplate for the given EntityManager.
|
||||
* @see #createJpaTemplate
|
||||
* @see #setJpaTemplate
|
||||
*/
|
||||
public final void setEntityManager(EntityManager entityManager) {
|
||||
this.jpaTemplate = createJpaTemplate(entityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JpaTemplate for the given EntityManager.
|
||||
* Only invoked if populating the DAO with a EntityManager reference!
|
||||
* <p>Can be overridden in subclasses to provide a JpaTemplate instance
|
||||
* with different configuration, or a custom JpaTemplate subclass.
|
||||
* @param entityManager the JPA EntityManager to create a JpaTemplate for
|
||||
* @return the new JpaTemplate instance
|
||||
* @see #setEntityManagerFactory
|
||||
*/
|
||||
protected JpaTemplate createJpaTemplate(EntityManager entityManager) {
|
||||
return new JpaTemplate(entityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JpaTemplate for this DAO explicitly,
|
||||
* as an alternative to specifying a EntityManagerFactory.
|
||||
* @see #setEntityManagerFactory
|
||||
*/
|
||||
public final void setJpaTemplate(JpaTemplate jpaTemplate) {
|
||||
this.jpaTemplate = jpaTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JpaTemplate for this DAO, pre-initialized
|
||||
* with the EntityManagerFactory or set explicitly.
|
||||
*/
|
||||
public final JpaTemplate getJpaTemplate() {
|
||||
return jpaTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void checkDaoConfig() {
|
||||
if (this.jpaTemplate == null) {
|
||||
throw new IllegalArgumentException("entityManagerFactory or jpaTemplate is required");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -61,9 +61,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
|||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see OpenEntityManagerInViewInterceptor
|
||||
* @see org.springframework.orm.jpa.JpaInterceptor
|
||||
* @see org.springframework.orm.jpa.JpaTransactionManager
|
||||
* @see org.springframework.orm.jpa.JpaTemplate#execute
|
||||
* @see org.springframework.orm.jpa.SharedEntityManagerCreator
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.orm.jpa.support;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
|
@ -49,16 +48,12 @@ import org.springframework.web.context.request.async.WebAsyncUtils;
|
|||
*
|
||||
* <p>In contrast to {@link OpenEntityManagerInViewFilter}, this interceptor
|
||||
* is set up in a Spring application context and can thus take advantage of
|
||||
* bean wiring. It inherits common JPA configuration properties from
|
||||
* {@link org.springframework.orm.jpa.JpaAccessor}, to be configured in a
|
||||
* bean definition.
|
||||
* bean wiring.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see OpenEntityManagerInViewFilter
|
||||
* @see org.springframework.orm.jpa.JpaInterceptor
|
||||
* @see org.springframework.orm.jpa.JpaTransactionManager
|
||||
* @see org.springframework.orm.jpa.JpaTemplate#execute
|
||||
* @see org.springframework.orm.jpa.SharedEntityManagerCreator
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
|
|
|
@ -23,8 +23,6 @@ import org.springframework.beans.factory.FactoryBean;
|
|||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryAccessor;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
||||
import org.springframework.orm.jpa.EntityManagerPlus;
|
||||
import org.springframework.orm.jpa.JpaDialect;
|
||||
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
@ -88,7 +86,6 @@ public class SharedEntityManagerBean extends EntityManagerFactoryAccessor
|
|||
if (emf == null) {
|
||||
throw new IllegalArgumentException("'entityManagerFactory' or 'persistenceUnitName' is required");
|
||||
}
|
||||
Class[] ifcs = null;
|
||||
if (emf instanceof EntityManagerFactoryInfo) {
|
||||
EntityManagerFactoryInfo emfInfo = (EntityManagerFactoryInfo) emf;
|
||||
if (this.entityManagerInterface == null) {
|
||||
|
@ -97,22 +94,14 @@ public class SharedEntityManagerBean extends EntityManagerFactoryAccessor
|
|||
this.entityManagerInterface = EntityManager.class;
|
||||
}
|
||||
}
|
||||
JpaDialect jpaDialect = emfInfo.getJpaDialect();
|
||||
if (jpaDialect != null && jpaDialect.supportsEntityManagerPlusOperations()) {
|
||||
ifcs = new Class[] {this.entityManagerInterface, EntityManagerPlus.class};
|
||||
}
|
||||
else {
|
||||
ifcs = new Class[] {this.entityManagerInterface};
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityManagerInterface == null) {
|
||||
this.entityManagerInterface = EntityManager.class;
|
||||
}
|
||||
ifcs = new Class[] {this.entityManagerInterface};
|
||||
}
|
||||
this.shared = SharedEntityManagerCreator.createSharedEntityManager(
|
||||
emf, getJpaPropertyMap(), this.synchronizedWithTransaction, ifcs);
|
||||
emf, getJpaPropertyMap(), this.synchronizedWithTransaction, this.entityManagerInterface);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Classes supporting the {@code org.springframework.orm.jpa} package.
|
||||
* Contains a DAO base class for JpaTemplate usage.
|
||||
*
|
||||
*/
|
||||
package org.springframework.orm.jpa.support;
|
||||
|
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.aopalliance.intercept.Interceptor;
|
||||
import org.aopalliance.intercept.Invocation;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JpaInterceptorTests {
|
||||
|
||||
private EntityManagerFactory factory;
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
factory = mock(EntityManagerFactory.class);
|
||||
entityManager = mock(EntityManager.class);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithNewEntityManager() throws PersistenceException {
|
||||
given(factory.createEntityManager()).willReturn(entityManager);
|
||||
given(entityManager.isOpen()).willReturn(true);
|
||||
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fail("Should not have thrown Throwable: " + t.getMessage());
|
||||
}
|
||||
|
||||
verify(entityManager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithNewEntityManagerAndLazyFlush() throws PersistenceException {
|
||||
given(factory.createEntityManager()).willReturn(entityManager);
|
||||
given(entityManager.isOpen()).willReturn(true);
|
||||
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setFlushEager(false);
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fail("Should not have thrown Throwable: " + t.getMessage());
|
||||
}
|
||||
|
||||
verify(entityManager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithThreadBound() {
|
||||
TransactionSynchronizationManager.bindResource(factory, new EntityManagerHolder(entityManager));
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fail("Should not have thrown Throwable: " + t.getMessage());
|
||||
}
|
||||
finally {
|
||||
TransactionSynchronizationManager.unbindResource(factory);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithThreadBoundAndFlushEager() throws PersistenceException {
|
||||
TransactionSynchronizationManager.bindResource(factory, new EntityManagerHolder(entityManager));
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setFlushEager(true);
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fail("Should not have thrown Throwable: " + t.getMessage());
|
||||
}
|
||||
finally {
|
||||
TransactionSynchronizationManager.unbindResource(factory);
|
||||
}
|
||||
|
||||
verify(entityManager).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithThreadBoundAndFlushCommit() {
|
||||
TransactionSynchronizationManager.bindResource(factory, new EntityManagerHolder(entityManager));
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setFlushEager(false);
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fail("Should not have thrown Throwable: " + t.getMessage());
|
||||
}
|
||||
finally {
|
||||
TransactionSynchronizationManager.unbindResource(factory);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithFlushFailure() throws Throwable {
|
||||
given(factory.createEntityManager()).willReturn(entityManager);
|
||||
|
||||
PersistenceException exception = new PersistenceException();
|
||||
willThrow(exception).given(entityManager).flush();
|
||||
given(entityManager.isOpen()).willReturn(true);
|
||||
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setFlushEager(true);
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
//fail("Should have thrown JpaSystemException");
|
||||
}
|
||||
catch (JpaSystemException ex) {
|
||||
// expected
|
||||
assertEquals(exception, ex.getCause());
|
||||
}
|
||||
|
||||
verify(entityManager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorWithFlushFailureWithoutConversion() throws Throwable {
|
||||
given(factory.createEntityManager()).willReturn(entityManager);
|
||||
|
||||
PersistenceException exception = new PersistenceException();
|
||||
willThrow(exception).given(entityManager).flush();
|
||||
given(entityManager.isOpen()).willReturn(true);
|
||||
|
||||
JpaInterceptor interceptor = new JpaInterceptor();
|
||||
interceptor.setFlushEager(true);
|
||||
interceptor.setExceptionConversionEnabled(false);
|
||||
interceptor.setEntityManagerFactory(factory);
|
||||
try {
|
||||
interceptor.invoke(new TestInvocation(factory));
|
||||
//fail("Should have thrown JpaSystemException");
|
||||
}
|
||||
catch (PersistenceException ex) {
|
||||
// expected
|
||||
assertEquals(exception, ex);
|
||||
}
|
||||
|
||||
verify(entityManager).close();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestInvocation implements MethodInvocation {
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
public TestInvocation(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object proceed() throws Throwable {
|
||||
if (!TransactionSynchronizationManager.hasResource(this.entityManagerFactory)) {
|
||||
throw new IllegalStateException("Session not bound");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getCurrentInterceptorIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getNumberOfInterceptors() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Interceptor getInterceptor(int i) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleObject getStaticPart() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getArgument(int i) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArguments() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setArgument(int i, Object handler) {
|
||||
}
|
||||
|
||||
public int getArgumentCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getProxy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Invocation cloneInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,412 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JpaTemplateTests {
|
||||
|
||||
private JpaTemplate template;
|
||||
|
||||
private EntityManager manager;
|
||||
|
||||
private EntityManagerFactory factory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
template = new JpaTemplate();
|
||||
|
||||
factory = mock(EntityManagerFactory.class);
|
||||
manager = mock(EntityManager.class);
|
||||
|
||||
template.setEntityManager(manager);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.JpaTemplate(EntityManagerFactory)'
|
||||
*/
|
||||
@Test
|
||||
public void testJpaTemplateEntityManagerFactory() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.JpaTemplate(EntityManager)'
|
||||
*/
|
||||
@Test
|
||||
public void testJpaTemplateEntityManager() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.execute(JpaCallback)'
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteJpaCallback() {
|
||||
template.setExposeNativeEntityManager(true);
|
||||
template.setEntityManager(manager);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
template.execute(new JpaCallback() {
|
||||
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
assertSame(em, manager);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
template.setExposeNativeEntityManager(false);
|
||||
template.execute(new JpaCallback() {
|
||||
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
assertNotSame(em, manager);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.executeFind(JpaCallback)'
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteFind() {
|
||||
template.setEntityManager(manager);
|
||||
template.setExposeNativeEntityManager(true);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
try {
|
||||
template.executeFind(new JpaCallback() {
|
||||
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
assertSame(em, manager);
|
||||
return new Object();
|
||||
}
|
||||
});
|
||||
fail("should have thrown exception");
|
||||
}
|
||||
catch (DataAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.execute(JpaCallback, boolean)'
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteJpaCallbackBoolean() {
|
||||
template = new JpaTemplate();
|
||||
template.setExposeNativeEntityManager(false);
|
||||
template.setEntityManagerFactory(factory);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
given(factory.createEntityManager()).willReturn(manager);
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
manager.close();
|
||||
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
assertSame(em, manager);
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteJpaCallbackBooleanWithPrebound() {
|
||||
template.setExposeNativeEntityManager(false);
|
||||
template.setEntityManagerFactory(factory);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
TransactionSynchronizationManager.bindResource(factory, new EntityManagerHolder(manager));
|
||||
|
||||
try {
|
||||
template.execute(new JpaCallback() {
|
||||
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
assertSame(em, manager);
|
||||
return null;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
finally {
|
||||
TransactionSynchronizationManager.unbindResource(factory);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.createSharedEntityManager(EntityManager)'
|
||||
*/
|
||||
@Test
|
||||
public void testCreateEntityManagerProxy() {
|
||||
|
||||
EntityManager proxy = template.createEntityManagerProxy(manager);
|
||||
assertNotSame(manager, proxy);
|
||||
assertFalse(manager.equals(proxy));
|
||||
assertFalse(manager.hashCode() == proxy.hashCode());
|
||||
// close call not propagated to the em
|
||||
proxy.close();
|
||||
proxy.clear();
|
||||
|
||||
verify(manager).clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.find(Class<T>,
|
||||
* Object) <T>'
|
||||
*/
|
||||
@Test
|
||||
public void testFindClassOfTObject() {
|
||||
Integer result = new Integer(1);
|
||||
Object id = new Object();
|
||||
given(manager.find(Number.class, id)).willReturn(result);
|
||||
|
||||
assertSame(result, template.find(Number.class, id));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.getReference(Class<T>, Object)
|
||||
* <T>'
|
||||
*/
|
||||
@Test
|
||||
public void testGetReference() {
|
||||
Integer reference = new Integer(1);
|
||||
Object id = new Object();
|
||||
given(manager.getReference(Number.class, id)).willReturn(reference);
|
||||
|
||||
assertSame(reference, template.getReference(Number.class, id));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.contains(Object)'
|
||||
*/
|
||||
@Test
|
||||
public void testContains() {
|
||||
boolean result = true;
|
||||
Object entity = new Object();
|
||||
given(manager.contains(entity)).willReturn(result);
|
||||
|
||||
assertSame(result, template.contains(entity));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.refresh(Object)'
|
||||
*/
|
||||
@Test
|
||||
public void testRefresh() {
|
||||
Object entity = new Object();
|
||||
template.refresh(entity);
|
||||
verify(manager).refresh(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.persist(Object)'
|
||||
*/
|
||||
@Test
|
||||
public void testPersist() {
|
||||
Object entity = new Object();
|
||||
template.persist(entity);
|
||||
verify(manager).persist(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.merge(T) <T>'
|
||||
*/
|
||||
@Test
|
||||
public void testMerge() {
|
||||
Object result = new Object();
|
||||
Object entity = new Object();
|
||||
given(manager.merge(entity)).willReturn(result);
|
||||
assertSame(result, template.merge(entity));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.remove(Object)'
|
||||
*/
|
||||
@Test
|
||||
public void testRemove() {
|
||||
Object entity = new Object();
|
||||
template.remove(entity);
|
||||
verify(manager).remove(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.flush()'
|
||||
*/
|
||||
@Test
|
||||
public void testFlush() {
|
||||
template.flush();
|
||||
verify(manager).flush();
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.find(String)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindString() {
|
||||
String queryString = "some query";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
|
||||
given(manager.createQuery(queryString)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
assertSame(result, template.find(queryString));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.find(String,
|
||||
* Object...)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindStringObjectArray() {
|
||||
String queryString = "some query";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
Object param1 = new Object();
|
||||
Object param2 = new Object();
|
||||
Object[] params = new Object[] { param1, param2 };
|
||||
|
||||
given(manager.createQuery(queryString)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
|
||||
assertSame(result, template.find(queryString, params));
|
||||
|
||||
verify(query).setParameter(1, param1);
|
||||
verify(query).setParameter(2, param2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.springframework.orm.jpa.JpaTemplate.find(String, Map<String,
|
||||
* Object>)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindStringMapOfStringObject() {
|
||||
String queryString = "some query";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
Object param1 = new Object();
|
||||
Object param2 = new Object();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("param1", param1);
|
||||
params.put("param2", param2);
|
||||
|
||||
given(manager.createQuery(queryString)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
|
||||
assertSame(result, template.findByNamedParams(queryString, params));
|
||||
|
||||
verify(query).setParameter("param1", param1);
|
||||
verify(query).setParameter("param2", param2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.findByNamedQuery(String)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindByNamedQueryString() {
|
||||
String queryName = "some query name";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
|
||||
given(manager.createNamedQuery(queryName)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
|
||||
assertSame(result, template.findByNamedQuery(queryName));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.findByNamedQuery(String,
|
||||
* Object...)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindByNamedQueryStringObjectArray() {
|
||||
String queryName = "some query name";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
Object param1 = new Object();
|
||||
Object param2 = new Object();
|
||||
Object[] params = new Object[] { param1, param2 };
|
||||
|
||||
given(manager.createNamedQuery(queryName)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
|
||||
assertSame(result, template.findByNamedQuery(queryName, params));
|
||||
|
||||
verify(query).setParameter(1, param1);
|
||||
verify(query).setParameter(2, param2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.orm.jpa.JpaTemplate.findByNamedQuery(String, Map<String,
|
||||
* Object>)'
|
||||
*/
|
||||
@Test
|
||||
public void testFindByNamedQueryStringMapOfStringObject() {
|
||||
String queryName = "some query name";
|
||||
Query query = mock(Query.class);
|
||||
List result = new ArrayList();
|
||||
Object param1 = new Object();
|
||||
Object param2 = new Object();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("param1", param1);
|
||||
params.put("param2", param2);
|
||||
|
||||
given(manager.createNamedQuery(queryName)).willReturn(query);
|
||||
given(query.getResultList()).willReturn(result);
|
||||
|
||||
assertSame(result, template.findByNamedQueryAndNamedParams(queryName, params));
|
||||
verify(query).setParameter("param1", param1);
|
||||
verify(query).setParameter("param2", param2);
|
||||
}
|
||||
}
|
|
@ -58,8 +58,6 @@ public class JpaTransactionManagerTests {
|
|||
|
||||
private JpaTransactionManager transactionManager;
|
||||
|
||||
private JpaTemplate template;
|
||||
|
||||
private TransactionTemplate tt;
|
||||
|
||||
|
||||
|
@ -70,8 +68,6 @@ public class JpaTransactionManagerTests {
|
|||
tx = mock(EntityTransaction.class);
|
||||
|
||||
transactionManager = new JpaTransactionManager(factory);
|
||||
template = new JpaTemplate(factory);
|
||||
template.afterPropertiesSet();
|
||||
tt = new TransactionTemplate(transactionManager);
|
||||
|
||||
given(factory.createEntityManager()).willReturn(manager);
|
||||
|
@ -101,13 +97,8 @@ public class JpaTransactionManagerTests {
|
|||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertSame(l, result);
|
||||
|
@ -137,13 +128,8 @@ public class JpaTransactionManagerTests {
|
|||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertSame(l, result);
|
||||
|
@ -176,12 +162,8 @@ public class JpaTransactionManagerTests {
|
|||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
throw new RuntimeException("some exception");
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
throw new RuntimeException("some exception");
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
|
@ -213,12 +195,8 @@ public class JpaTransactionManagerTests {
|
|||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
throw new RuntimeException("some exception");
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
throw new RuntimeException("some exception");
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
|
@ -249,16 +227,10 @@ public class JpaTransactionManagerTests {
|
|||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
|
||||
Object res = template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
status.setRollbackOnly();
|
||||
|
||||
return res;
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -288,14 +260,8 @@ public class JpaTransactionManagerTests {
|
|||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -328,12 +294,8 @@ public class JpaTransactionManagerTests {
|
|||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
throw new RuntimeException("exception");
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
throw new RuntimeException("some exception");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -374,15 +336,7 @@ public class JpaTransactionManagerTests {
|
|||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
|
@ -425,13 +379,8 @@ public class JpaTransactionManagerTests {
|
|||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -464,25 +413,14 @@ public class JpaTransactionManagerTests {
|
|||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JpaTemplate template2 = new JpaTemplate(factory);
|
||||
template2.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -523,13 +461,8 @@ public class JpaTransactionManagerTests {
|
|||
return tt2.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -561,13 +494,7 @@ public class JpaTransactionManagerTests {
|
|||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JpaTemplate template2 = new JpaTemplate(factory);
|
||||
template2.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) throws PersistenceException {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
TransactionTemplate tt2 = new TransactionTemplate(transactionManager);
|
||||
|
@ -575,13 +502,8 @@ public class JpaTransactionManagerTests {
|
|||
return tt2.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -614,26 +536,15 @@ public class JpaTransactionManagerTests {
|
|||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em2) {
|
||||
em2.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -672,13 +583,8 @@ public class JpaTransactionManagerTests {
|
|||
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(!status.isNewTransaction());
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertSame(l, result);
|
||||
|
@ -705,13 +611,7 @@ public class JpaTransactionManagerTests {
|
|||
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(!status.isNewTransaction());
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
|
@ -741,12 +641,8 @@ public class JpaTransactionManagerTests {
|
|||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertSame(l, result);
|
||||
|
@ -778,12 +674,7 @@ public class JpaTransactionManagerTests {
|
|||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
|
@ -820,13 +711,8 @@ public class JpaTransactionManagerTests {
|
|||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(!status.isNewTransaction());
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertSame(l, result);
|
||||
|
@ -858,13 +744,7 @@ public class JpaTransactionManagerTests {
|
|||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(!status.isNewTransaction());
|
||||
template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
|
@ -900,13 +780,8 @@ public class JpaTransactionManagerTests {
|
|||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
return template.execute(new JpaCallback() {
|
||||
@Override
|
||||
public Object doInJpa(EntityManager em) {
|
||||
em.flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.orm.jpa.JpaTemplate;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JpaDaoSupportTests {
|
||||
|
||||
@Test
|
||||
public void testJpaDaoSupportWithEntityManager() throws Exception {
|
||||
EntityManager entityManager = mock(EntityManager.class);
|
||||
final List test = new ArrayList();
|
||||
JpaDaoSupport dao = new JpaDaoSupport() {
|
||||
@Override
|
||||
protected void initDao() {
|
||||
test.add("test");
|
||||
}
|
||||
};
|
||||
dao.setEntityManager(entityManager);
|
||||
dao.afterPropertiesSet();
|
||||
assertNotNull("jpa template not created", dao.getJpaTemplate());
|
||||
assertEquals("incorrect entity manager", entityManager, dao.getJpaTemplate().getEntityManager());
|
||||
assertEquals("initDao not called", test.size(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpaDaoSupportWithEntityManagerFactory() throws Exception {
|
||||
EntityManagerFactory entityManagerFactory = mock(EntityManagerFactory.class);
|
||||
final List test = new ArrayList();
|
||||
JpaDaoSupport dao = new JpaDaoSupport() {
|
||||
@Override
|
||||
protected void initDao() {
|
||||
test.add("test");
|
||||
}
|
||||
};
|
||||
dao.setEntityManagerFactory(entityManagerFactory);
|
||||
dao.afterPropertiesSet();
|
||||
assertNotNull("jpa template not created", dao.getJpaTemplate());
|
||||
assertEquals("incorrect entity manager factory", entityManagerFactory,
|
||||
dao.getJpaTemplate().getEntityManagerFactory());
|
||||
assertEquals("initDao not called", test.size(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpaDaoSupportWithJpaTemplate() throws Exception {
|
||||
JpaTemplate template = new JpaTemplate();
|
||||
final List test = new ArrayList();
|
||||
JpaDaoSupport dao = new JpaDaoSupport() {
|
||||
@Override
|
||||
protected void initDao() {
|
||||
test.add("test");
|
||||
}
|
||||
};
|
||||
dao.setJpaTemplate(template);
|
||||
dao.afterPropertiesSet();
|
||||
assertNotNull("jpa template not created", dao.getJpaTemplate());
|
||||
assertEquals("incorrect JpaTemplate", template, dao.getJpaTemplate());
|
||||
assertEquals("initDao not called", test.size(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidJpaTemplate() throws Exception {
|
||||
JpaDaoSupport dao = new JpaDaoSupport() {
|
||||
};
|
||||
try {
|
||||
dao.afterPropertiesSet();
|
||||
fail("expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
// okay
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ package org.springframework.orm.jpa.support;
|
|||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.servlet.FilterChain;
|
||||
|
@ -30,13 +29,13 @@ import javax.servlet.ServletResponse;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.mock.web.test.MockFilterConfig;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.mock.web.test.PassThroughFilterChain;
|
||||
import org.springframework.orm.jpa.JpaTemplate;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
@ -60,17 +59,12 @@ public class OpenEntityManagerInViewTests {
|
|||
|
||||
private EntityManagerFactory factory;
|
||||
|
||||
private JpaTemplate template;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
factory = mock(EntityManagerFactory.class);
|
||||
manager = mock(EntityManager.class);
|
||||
|
||||
template = new JpaTemplate(factory);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
given(factory.createEntityManager()).willReturn(manager);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue