Removed deprecated JpaTemplate and JpaInterceptor classes; dropped unused EntityManager(Factory)Plus mechanism

This commit is contained in:
Juergen Hoeller 2013-03-29 13:18:33 +01:00
parent 7ceb02257e
commit 9caa514c69
28 changed files with 90 additions and 2350 deletions

View File

@ -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)

View File

@ -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");
}
}

View File

@ -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 {

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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();

View File

@ -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());
}
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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();
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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");
}
}
}

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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);
}

View File

@ -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;

View File

@ -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() {
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
});

View File

@ -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
}
}
}

View File

@ -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);
}