, InitializingBean {
private static final ThreadLocal configTimeLobHandlerHolder = new ThreadLocal();
@@ -333,24 +332,24 @@ public class SqlMapClientFactoryBean implements FactoryBean, InitializingBean {
SqlMapClient client = null;
SqlMapConfigParser configParser = new SqlMapConfigParser();
- for (int i = 0; i < configLocations.length; i++) {
- InputStream is = configLocations[i].getInputStream();
+ for (Resource configLocation : configLocations) {
+ InputStream is = configLocation.getInputStream();
try {
client = configParser.parse(is, properties);
}
catch (RuntimeException ex) {
- throw new NestedIOException("Failed to parse config resource: " + configLocations[i], ex.getCause());
+ throw new NestedIOException("Failed to parse config resource: " + configLocation, ex.getCause());
}
}
if (mappingLocations != null) {
SqlMapParser mapParser = SqlMapParserFactory.createSqlMapParser(configParser);
- for (int i = 0; i < mappingLocations.length; i++) {
+ for (Resource mappingLocation : mappingLocations) {
try {
- mapParser.parse(mappingLocations[i].getInputStream());
+ mapParser.parse(mappingLocation.getInputStream());
}
catch (NodeletException ex) {
- throw new NestedIOException("Failed to parse mapping resource: " + mappingLocations[i], ex);
+ throw new NestedIOException("Failed to parse mapping resource: " + mappingLocation, ex);
}
}
}
@@ -381,11 +380,11 @@ public class SqlMapClientFactoryBean implements FactoryBean, InitializingBean {
}
- public Object getObject() {
+ public SqlMapClient getObject() {
return this.sqlMapClient;
}
- public Class getObjectType() {
+ public Class extends SqlMapClient> getObjectType() {
return (this.sqlMapClient != null ? this.sqlMapClient.getClass() : SqlMapClient.class);
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/DefaultJdoDialect.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/DefaultJdoDialect.java
index 267613d619a5fee0aef1e1170251b6528ad26607..f90866596fc163cebaa796e88016958eadf3884e 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/DefaultJdoDialect.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/DefaultJdoDialect.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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.jdo;
import java.sql.Connection;
import java.sql.SQLException;
-
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
@@ -182,20 +181,13 @@ public class DefaultJdoDialect implements JdoDialect, PersistenceExceptionTransl
}
/**
- * This implementation delegates to JDO 2.0's flush
method.
- * To be overridden for pre-JDO2 implementations, using the corresponding
- * vendor-specific mechanism there.
- * @see javax.jdo.PersistenceManager#flush()
- */
- public void flush(PersistenceManager pm) throws JDOException {
- pm.flush();
- }
-
- /**
- * This implementation logs a warning that it cannot apply a query timeout.
+ * This implementation sets the JPA 2.0 query hints "javax.persistence.lock.timeout"
+ * and "javax.persistence.query.timeout", assuming that JDO 2.1 providers are often
+ * JPA providers as well.
*/
public void applyQueryTimeout(Query query, int remainingTimeInSeconds) throws JDOException {
- logger.info("DefaultJdoDialect does not support query timeouts: ignoring remaining transaction time");
+ query.addExtension("javax.persistence.lock.timeout", remainingTimeInSeconds);
+ query.addExtension("javax.persistence.query.timeout", remainingTimeInSeconds);
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoAccessor.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoAccessor.java
index cd7b17a583aadda8c3ac11bf52e23554eb4a557c..4cb9128d33a041de179a69c61d6f0864e24eba05 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoAccessor.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoAccessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -73,7 +73,7 @@ public abstract class JdoAccessor implements InitializingBean {
* PersistenceManagers.
*/
public PersistenceManagerFactory getPersistenceManagerFactory() {
- return persistenceManagerFactory;
+ return this.persistenceManagerFactory;
}
/**
@@ -120,7 +120,7 @@ public abstract class JdoAccessor implements InitializingBean {
* Return if this accessor should flush changes to the database eagerly.
*/
public boolean isFlushEager() {
- return flushEager;
+ return this.flushEager;
}
/**
@@ -129,7 +129,7 @@ public abstract class JdoAccessor implements InitializingBean {
*/
public void afterPropertiesSet() {
if (getPersistenceManagerFactory() == null) {
- throw new IllegalArgumentException("persistenceManagerFactory is required");
+ throw new IllegalArgumentException("Property 'persistenceManagerFactory' is required");
}
// Build default JdoDialect if none explicitly specified.
if (this.jdoDialect == null) {
@@ -148,7 +148,7 @@ public abstract class JdoAccessor implements InitializingBean {
protected void flushIfNecessary(PersistenceManager pm, boolean existingTransaction) throws JDOException {
if (isFlushEager()) {
logger.debug("Eagerly flushing JDO persistence manager");
- getJdoDialect().flush(pm);
+ pm.flush();
}
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoCallback.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoCallback.java
index ebcb2e72012e9cfd714735ccba3f7f1667f85ac5..dada9cf5cd00888aae73aa06885ca76bf8ac483b 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoCallback.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -41,7 +41,7 @@ import javax.jdo.PersistenceManager;
* @see JdoTemplate
* @see JdoTransactionManager
*/
-public interface JdoCallback {
+public interface JdoCallback {
/**
* Gets called by JdoTemplate.execute
with an active JDO
@@ -64,6 +64,6 @@ public interface JdoCallback {
* @see JdoTemplate#execute
* @see JdoTemplate#executeFind
*/
- Object doInJdo(PersistenceManager pm) throws JDOException;
+ T doInJdo(PersistenceManager pm) throws JDOException;
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoDialect.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoDialect.java
index 0246694be88764668515d2e4f75a7724cddc1764..91120706ff3ca32520ac6ce0f6c3dc595f4cce84 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoDialect.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoDialect.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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.jdo;
import java.sql.SQLException;
-
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
@@ -145,22 +144,11 @@ public interface JdoDialect {
void releaseJdbcConnection(ConnectionHandle conHandle, PersistenceManager pm)
throws JDOException, SQLException;
- /**
- * Flush the given PersistenceManager, i.e. flush all changes (that have been
- * applied to persistent objects) to the underlying database. This method will
- * just get invoked when eager flushing is actually necessary, for example when
- * JDBC access code needs to see changes within the same transaction.
- * @param pm the current JDO PersistenceManager
- * @throws JDOException in case of errors
- * @see JdoAccessor#setFlushEager
- */
- void flush(PersistenceManager pm) throws JDOException;
-
/**
* Apply the given timeout to the given JDO query object.
* Invoked with the remaining time of a specified transaction timeout, if any.
* @param query the JDO query object to apply the timeout to
- * @param timeout the timeout value to apply
+ * @param timeout the timeout value (seconds) to apply
* @throws JDOException if thrown by JDO methods
* @see JdoTemplate#prepareQuery
*/
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoOperations.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoOperations.java
index 71ddbec81eecd858a5680ec77ec7e4c805bd9be4..98ce77f200ad84e5236c2b209a2576f96b87cc17 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoOperations.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoOperations.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -67,7 +67,7 @@ public interface JdoOperations {
* @see org.springframework.transaction
* @see javax.jdo.PersistenceManager
*/
- Object execute(JdoCallback action) throws DataAccessException;
+ T execute(JdoCallback action) throws DataAccessException;
/**
* Execute the specified action assuming that the result object is a
@@ -77,7 +77,7 @@ public interface JdoOperations {
* @return a Collection result returned by the action, or null
* @throws org.springframework.dao.DataAccessException in case of JDO errors
*/
- Collection executeFind(JdoCallback action) throws DataAccessException;
+ Collection executeFind(JdoCallback> action) throws DataAccessException;
//-------------------------------------------------------------------------
@@ -113,7 +113,7 @@ public interface JdoOperations {
* @see javax.jdo.PersistenceManager#getObjectById(Object, boolean)
* @see javax.jdo.PersistenceManager#getObjectById(Class, Object)
*/
- Object getObjectById(Class entityClass, Object idValue) throws DataAccessException;
+ T getObjectById(Class entityClass, Object idValue) throws DataAccessException;
/**
* Remove the given object from the PersistenceManager cache.
@@ -169,7 +169,7 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#makePersistent(Object)
*/
- Object makePersistent(Object entity) throws DataAccessException;
+ T makePersistent(T entity) throws DataAccessException;
/**
* Make the given transient instances persistent.
@@ -179,7 +179,7 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#makePersistentAll(java.util.Collection)
*/
- Collection makePersistentAll(Collection entities) throws DataAccessException;
+ Collection makePersistentAll(Collection entities) throws DataAccessException;
/**
* Delete the given persistent instance.
@@ -206,7 +206,7 @@ public interface JdoOperations {
* @return the corresponding detached instance
* @see javax.jdo.PersistenceManager#detachCopy(Object)
*/
- Object detachCopy(Object entity);
+ T detachCopy(T entity);
/**
* Detach copies of the given persistent instances from the current JDO transaction,
@@ -215,7 +215,7 @@ public interface JdoOperations {
* @return the corresponding detached instances
* @see javax.jdo.PersistenceManager#detachCopyAll(Collection)
*/
- Collection detachCopyAll(Collection entities);
+ Collection detachCopyAll(Collection entities);
/**
* Flush all transactional modifications to the database.
@@ -240,7 +240,7 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#newQuery(Class)
*/
- Collection find(Class entityClass) throws DataAccessException;
+ Collection find(Class entityClass) throws DataAccessException;
/**
* Find all persistent instances of the given class that match the given
@@ -251,7 +251,7 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#newQuery(Class, String)
*/
- Collection find(Class entityClass, String filter) throws DataAccessException;
+ Collection find(Class entityClass, String filter) throws DataAccessException;
/**
* Find all persistent instances of the given class that match the given
@@ -264,7 +264,7 @@ public interface JdoOperations {
* @see javax.jdo.PersistenceManager#newQuery(Class, String)
* @see javax.jdo.Query#setOrdering
*/
- Collection find(Class entityClass, String filter, String ordering) throws DataAccessException;
+ Collection find(Class entityClass, String filter, String ordering) throws DataAccessException;
/**
* Find all persistent instances of the given class that match the given
@@ -279,7 +279,7 @@ public interface JdoOperations {
* @see javax.jdo.Query#declareParameters
* @see javax.jdo.Query#executeWithArray
*/
- Collection find(Class entityClass, String filter, String parameters, Object[] values)
+ Collection find(Class entityClass, String filter, String parameters, Object[] values)
throws DataAccessException;
/**
@@ -298,7 +298,7 @@ public interface JdoOperations {
* @see javax.jdo.Query#executeWithArray
* @see javax.jdo.Query#setOrdering
*/
- Collection find(Class entityClass, String filter, String parameters, Object[] values, String ordering)
+ Collection find(Class entityClass, String filter, String parameters, Object[] values, String ordering)
throws DataAccessException;
/**
@@ -314,7 +314,7 @@ public interface JdoOperations {
* @see javax.jdo.Query#declareParameters
* @see javax.jdo.Query#executeWithMap
*/
- Collection find(Class entityClass, String filter, String parameters, Map values)
+ Collection find(Class entityClass, String filter, String parameters, Map values)
throws DataAccessException;
/**
@@ -333,7 +333,7 @@ public interface JdoOperations {
* @see javax.jdo.Query#executeWithMap
* @see javax.jdo.Query#setOrdering
*/
- Collection find(Class entityClass, String filter, String parameters, Map values, String ordering)
+ Collection find(Class entityClass, String filter, String parameters, Map values, String ordering)
throws DataAccessException;
/**
@@ -387,7 +387,8 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#newNamedQuery(Class, String)
*/
- Collection findByNamedQuery(Class entityClass, String queryName) throws DataAccessException;
+ Collection findByNamedQuery(Class entityClass, String queryName)
+ throws DataAccessException;
/**
* Find persistent instances through the given named query.
@@ -398,7 +399,8 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#newNamedQuery(Class, String)
*/
- Collection findByNamedQuery(Class entityClass, String queryName, Object[] values) throws DataAccessException;
+ Collection findByNamedQuery(Class entityClass, String queryName, Object[] values)
+ throws DataAccessException;
/**
* Find persistent instances through the given named query.
@@ -409,6 +411,7 @@ public interface JdoOperations {
* @throws org.springframework.dao.DataAccessException in case of JDO errors
* @see javax.jdo.PersistenceManager#newNamedQuery(Class, String)
*/
- Collection findByNamedQuery(Class entityClass, String queryName, Map values) throws DataAccessException;
+ Collection findByNamedQuery(Class entityClass, String queryName, Map values)
+ throws DataAccessException;
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoTemplate.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoTemplate.java
index 6c1338823391cef1ccedbe6102685177b154061d..3d525422f3a661fc8385b88a1b48a2938f9786fd 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoTemplate.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/JdoTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -22,7 +22,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Map;
-
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
@@ -77,6 +76,8 @@ import org.springframework.util.ClassUtils;
* for example: evict
, evictAll
, flush
.
*
* NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.
+ * As of Spring 3.0, it follows JDO 2.1 conventions in terms of generic
+ * parameter and return types, which still remaining compatible with JDO 2.0.
*
* @author Juergen Hoeller
* @since 03.06.2003
@@ -170,11 +171,11 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
- public Object execute(JdoCallback action) throws DataAccessException {
+ public T execute(JdoCallback action) throws DataAccessException {
return execute(action, isExposeNativePersistenceManager());
}
- public Collection executeFind(JdoCallback action) throws DataAccessException {
+ public Collection executeFind(JdoCallback> action) throws DataAccessException {
Object result = execute(action, isExposeNativePersistenceManager());
if (result != null && !(result instanceof Collection)) {
throw new InvalidDataAccessApiUsageException(
@@ -192,7 +193,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
* @return a result object returned by the action, or null
* @throws org.springframework.dao.DataAccessException in case of JDO errors
*/
- public Object execute(JdoCallback action, boolean exposeNativePersistenceManager) throws DataAccessException {
+ public T execute(JdoCallback action, boolean exposeNativePersistenceManager) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager(
@@ -201,7 +202,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
TransactionSynchronizationManager.hasResource(getPersistenceManagerFactory());
try {
PersistenceManager pmToExpose = (exposeNativePersistenceManager ? pm : createPersistenceManagerProxy(pm));
- Object result = action.doInJdo(pmToExpose);
+ T result = action.doInJdo(pmToExpose);
flushIfNecessary(pm, existingTransaction);
return postProcessResult(result, pm, existingTransaction);
}
@@ -248,7 +249,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
* @return the post-processed result object (can be simply be the passed-in object)
* @see #execute(JdoCallback, boolean)
*/
- protected Object postProcessResult(Object result, PersistenceManager pm, boolean existingTransaction) {
+ protected T postProcessResult(T result, PersistenceManager pm, boolean existingTransaction) {
return result;
}
@@ -258,23 +259,23 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
//-------------------------------------------------------------------------
public Object getObjectById(final Object objectId) throws DataAccessException {
- return execute(new JdoCallback() {
+ return execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
return pm.getObjectById(objectId, true);
}
}, true);
}
- public Object getObjectById(final Class entityClass, final Object idValue) throws DataAccessException {
- return execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public T getObjectById(final Class entityClass, final Object idValue) throws DataAccessException {
+ return execute(new JdoCallback() {
+ public T doInJdo(PersistenceManager pm) throws JDOException {
return pm.getObjectById(entityClass, idValue);
}
}, true);
}
public void evict(final Object entity) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.evict(entity);
return null;
@@ -283,7 +284,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void evictAll(final Collection entities) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.evictAll(entities);
return null;
@@ -292,7 +293,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void evictAll() throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.evictAll();
return null;
@@ -301,7 +302,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void refresh(final Object entity) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.refresh(entity);
return null;
@@ -310,7 +311,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void refreshAll(final Collection entities) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.refreshAll(entities);
return null;
@@ -319,7 +320,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void refreshAll() throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.refreshAll();
return null;
@@ -327,24 +328,24 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}, true);
}
- public Object makePersistent(final Object entity) throws DataAccessException {
- return execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public T makePersistent(final T entity) throws DataAccessException {
+ return execute(new JdoCallback() {
+ public T doInJdo(PersistenceManager pm) throws JDOException {
return pm.makePersistent(entity);
}
}, true);
}
- public Collection makePersistentAll(final Collection entities) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public Collection makePersistentAll(final Collection entities) throws DataAccessException {
+ return execute(new JdoCallback>() {
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
return pm.makePersistentAll(entities);
}
}, true);
}
public void deletePersistent(final Object entity) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.deletePersistent(entity);
return null;
@@ -353,7 +354,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}
public void deletePersistentAll(final Collection entities) throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
pm.deletePersistentAll(entities);
return null;
@@ -361,26 +362,26 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
}, true);
}
- public Object detachCopy(final Object entity) {
- return execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public T detachCopy(final T entity) {
+ return execute(new JdoCallback() {
+ public T doInJdo(PersistenceManager pm) throws JDOException {
return pm.detachCopy(entity);
}
}, true);
}
- public Collection detachCopyAll(final Collection entities) {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public Collection detachCopyAll(final Collection entities) {
+ return execute(new JdoCallback>() {
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
return pm.detachCopyAll(entities);
}
}, true);
}
public void flush() throws DataAccessException {
- execute(new JdoCallback() {
+ execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
- getJdoDialect().flush(pm);
+ pm.flush();
return null;
}
}, true);
@@ -391,145 +392,154 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
// Convenience finder methods
//-------------------------------------------------------------------------
- public Collection find(Class entityClass) throws DataAccessException {
+ public Collection find(Class entityClass) throws DataAccessException {
return find(entityClass, null, null);
}
- public Collection find(Class entityClass, String filter) throws DataAccessException {
+ public Collection find(Class entityClass, String filter) throws DataAccessException {
return find(entityClass, filter, null);
}
- public Collection find(final Class entityClass, final String filter, final String ordering)
+ public Collection find(final Class entityClass, final String filter, final String ordering)
throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = (filter != null ? pm.newQuery(entityClass, filter) : pm.newQuery(entityClass));
prepareQuery(query);
if (ordering != null) {
query.setOrdering(ordering);
}
- return query.execute();
+ return (Collection) query.execute();
}
}, true);
}
- public Collection find(Class entityClass, String filter, String parameters, Object[] values)
+ public Collection find(Class entityClass, String filter, String parameters, Object... values)
throws DataAccessException {
return find(entityClass, filter, parameters, values, null);
}
- public Collection find(
- final Class entityClass, final String filter, final String parameters, final Object[] values,
+ public Collection find(
+ final Class entityClass, final String filter, final String parameters, final Object[] values,
final String ordering) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(entityClass, filter);
prepareQuery(query);
query.declareParameters(parameters);
if (ordering != null) {
query.setOrdering(ordering);
}
- return query.executeWithArray(values);
+ return (Collection) query.executeWithArray(values);
}
}, true);
}
- public Collection find(Class entityClass, String filter, String parameters, Map values)
+ public Collection find(Class entityClass, String filter, String parameters, Map values)
throws DataAccessException {
return find(entityClass, filter, parameters, values, null);
}
- public Collection find(
- final Class entityClass, final String filter, final String parameters, final Map values,
+ public Collection find(
+ final Class entityClass, final String filter, final String parameters, final Map values,
final String ordering) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(entityClass, filter);
prepareQuery(query);
query.declareParameters(parameters);
if (ordering != null) {
query.setOrdering(ordering);
}
- return query.executeWithMap(values);
+ return (Collection) query.executeWithMap(values);
}
}, true);
}
public Collection find(final String language, final Object queryObject) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback() {
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(language, queryObject);
prepareQuery(query);
- return query.execute();
+ return (Collection) query.execute();
}
}, true);
}
public Collection find(final String queryString) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(queryString);
prepareQuery(query);
- return query.execute();
+ return (Collection) query.execute();
}
}, true);
}
public Collection find(final String queryString, final Object[] values) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback() {
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(queryString);
prepareQuery(query);
- return query.executeWithArray(values);
+ return (Collection) query.executeWithArray(values);
}
}, true);
}
public Collection find(final String queryString, final Map values) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback() {
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(queryString);
prepareQuery(query);
- return query.executeWithMap(values);
+ return (Collection) query.executeWithMap(values);
}
}, true);
}
- public Collection findByNamedQuery(final Class entityClass, final String queryName) throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ public Collection findByNamedQuery(final Class entityClass, final String queryName)
+ throws DataAccessException {
+
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
- return query.execute();
+ return (Collection) query.execute();
}
}, true);
}
- public Collection findByNamedQuery(final Class entityClass, final String queryName, final Object[] values)
+ public Collection findByNamedQuery(final Class entityClass, final String queryName, final Object[] values)
throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
- return query.executeWithArray(values);
+ return (Collection) query.executeWithArray(values);
}
}, true);
}
- public Collection findByNamedQuery(final Class entityClass, final String queryName, final Map values)
+ public Collection findByNamedQuery(final Class entityClass, final String queryName, final Map values)
throws DataAccessException {
- return (Collection) execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
+ return execute(new JdoCallback>() {
+ @SuppressWarnings("unchecked")
+ public Collection doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
- return query.executeWithMap(values);
+ return (Collection) query.executeWithMap(values);
}
}, true);
}
@@ -537,7 +547,7 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
/**
* Prepare the given JDO query object. To be used within a JdoCallback.
- * Applies a transaction timeout, if any. If you don't use such timeouts,
+ * Applies a transaction timeout, if any. If you don't use such timeouts,
* the call is a no-op.
*
In general, prefer a proxied PersistenceManager instead, which will
* automatically apply the transaction timeout (through the use of a special
@@ -588,12 +598,10 @@ public class JdoTemplate extends JdoAccessor implements JdoOperations {
// Invoke method on target PersistenceManager.
try {
Object retVal = method.invoke(this.target, args);
-
// If return value is a JDO Query object, apply transaction timeout.
if (retVal instanceof Query) {
prepareQuery(((Query) retVal));
}
-
return retVal;
}
catch (InvocationTargetException ex) {
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryBean.java
index 9730af99774e986ba5fc33f0186f7ac08e000a5a..09ce80a2dd5a68b2562f451e3dcad575cfac0d24 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryBean.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -20,7 +20,6 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-
import javax.jdo.JDOException;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
@@ -46,6 +45,12 @@ import org.springframework.util.CollectionUtils;
* dependency injection. Note that switching to a JNDI lookup or to a bean-style
* PersistenceManagerFactory instance is just a matter of configuration!
*
+ *
NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.
+ * Since JDO 2.1, it will also expose the JPA {@link javax.persistence.EntityManagerFactory}
+ * as long as the JDO provider creates a {@link javax.jdo.JDOEntityManagerFactory} reference
+ * underneath, which means that this class can be used as a replacement for
+ * {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean} in such a scenario.
+ *
*
Configuration settings can either be read from a properties file,
* specified as "configLocation", or locally specified. Properties
* specified as "jdoProperties" here will override any settings in a file.
@@ -53,8 +58,6 @@ import org.springframework.util.CollectionUtils;
* referring to a PMF definition in "META-INF/jdoconfig.xml"
* (see {@link #setPersistenceManagerFactoryName}).
*
- *
NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.
- *
*
This class also implements the
* {@link org.springframework.dao.support.PersistenceExceptionTranslator}
* interface, as autodetected by Spring's
@@ -105,8 +108,8 @@ import org.springframework.util.CollectionUtils;
* @see javax.jdo.PersistenceManagerFactory#close()
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
*/
-public class LocalPersistenceManagerFactoryBean
- implements FactoryBean, BeanClassLoaderAware, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
+public class LocalPersistenceManagerFactoryBean implements FactoryBean,
+ BeanClassLoaderAware, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
protected final Log logger = LogFactory.getLog(getClass());
@@ -272,11 +275,11 @@ public class LocalPersistenceManagerFactoryBean
/**
* Return the singleton PersistenceManagerFactory.
*/
- public Object getObject() {
+ public PersistenceManagerFactory getObject() {
return this.persistenceManagerFactory;
}
- public Class getObjectType() {
+ public Class extends PersistenceManagerFactory> getObjectType() {
return (this.persistenceManagerFactory != null ?
this.persistenceManagerFactory.getClass() : PersistenceManagerFactory.class);
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/PersistenceManagerFactoryUtils.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/PersistenceManagerFactoryUtils.java
index 03b52f1d12290e21c7d7b885272b5b60f45a2152..d6bafa45155ebd54bf91c7a758f9c2184682c255 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/PersistenceManagerFactoryUtils.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/PersistenceManagerFactoryUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/TransactionAwarePersistenceManagerFactoryProxy.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/TransactionAwarePersistenceManagerFactoryProxy.java
index 30a3772efcd13f01a08890163b6bfe598d193071..a01ba2f117d51edb1075bd868d9247a1c61dbb99 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/TransactionAwarePersistenceManagerFactoryProxy.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/TransactionAwarePersistenceManagerFactoryProxy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -20,7 +20,6 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
-
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
@@ -31,7 +30,7 @@ import org.springframework.util.ClassUtils;
/**
* Proxy for a target JDO {@link javax.jdo.PersistenceManagerFactory},
* returning the current thread-bound PersistenceManager (the Spring-managed
- * transactional PersistenceManager or a the single OpenPersistenceManagerInView
+ * transactional PersistenceManager or the single OpenPersistenceManagerInView
* PersistenceManager) on getPersistenceManager()
, if any.
*
* Essentially, getPersistenceManager()
calls get seamlessly
@@ -68,7 +67,7 @@ import org.springframework.util.ClassUtils;
* @see PersistenceManagerFactoryUtils#getPersistenceManager
* @see PersistenceManagerFactoryUtils#releasePersistenceManager
*/
-public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBean {
+public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBean {
private PersistenceManagerFactory target;
@@ -86,9 +85,9 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
public void setTargetPersistenceManagerFactory(PersistenceManagerFactory target) {
Assert.notNull(target, "Target PersistenceManagerFactory must not be null");
this.target = target;
- Class[] ifcs = ClassUtils.getAllInterfacesForClass(target.getClass(), getClass().getClassLoader());
+ Class[] ifcs = ClassUtils.getAllInterfacesForClass(target.getClass(), target.getClass().getClassLoader());
this.proxy = (PersistenceManagerFactory) Proxy.newProxyInstance(
- target.getClass().getClassLoader(), ifcs, new TransactionAwareFactoryInvocationHandler());
+ target.getClass().getClassLoader(), ifcs, new PersistenceManagerFactoryInvocationHandler());
}
/**
@@ -123,11 +122,11 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
}
- public Object getObject() {
+ public PersistenceManagerFactory getObject() {
return this.proxy;
}
- public Class getObjectType() {
+ public Class extends PersistenceManagerFactory> getObjectType() {
return PersistenceManagerFactory.class;
}
@@ -141,7 +140,7 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
* PersistenceManagerFactory proxy to PersistenceManagerFactoryUtils
* for being aware of thread-bound transactions.
*/
- private class TransactionAwareFactoryInvocationHandler implements InvocationHandler {
+ private class PersistenceManagerFactoryInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on PersistenceManagerFactory interface coming in...
@@ -158,9 +157,9 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
PersistenceManagerFactory target = getTargetPersistenceManagerFactory();
PersistenceManager pm =
PersistenceManagerFactoryUtils.doGetPersistenceManager(target, isAllowCreate());
- Class[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), getClass().getClassLoader());
+ Class[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), pm.getClass().getClassLoader());
return Proxy.newProxyInstance(
- pm.getClass().getClassLoader(), ifcs, new TransactionAwareInvocationHandler(pm, target));
+ pm.getClass().getClassLoader(), ifcs, new PersistenceManagerInvocationHandler(pm, target));
}
// Invoke method on target PersistenceManagerFactory.
@@ -178,13 +177,13 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
* Invocation handler that delegates close calls on PersistenceManagers to
* PersistenceManagerFactoryUtils for being aware of thread-bound transactions.
*/
- private static class TransactionAwareInvocationHandler implements InvocationHandler {
+ private static class PersistenceManagerInvocationHandler implements InvocationHandler {
private final PersistenceManager target;
private final PersistenceManagerFactory persistenceManagerFactory;
- public TransactionAwareInvocationHandler(PersistenceManager target, PersistenceManagerFactory pmf) {
+ public PersistenceManagerInvocationHandler(PersistenceManager target, PersistenceManagerFactory pmf) {
this.target = target;
this.persistenceManagerFactory = pmf;
}
@@ -202,10 +201,8 @@ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBe
}
else if (method.getName().equals("close")) {
// Handle close method: only close if not within a transaction.
- if (this.persistenceManagerFactory != null) {
- PersistenceManagerFactoryUtils.doReleasePersistenceManager(
- this.target, this.persistenceManagerFactory);
- }
+ PersistenceManagerFactoryUtils.doReleasePersistenceManager(
+ this.target, this.persistenceManagerFactory);
return null;
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewFilter.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewFilter.java
index d897114f0eccc67d7172b1a6f45df5e585416ec6..f3ad90ecfb4bf9de08e8dae4e63fab42e9a0862b 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewFilter.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -139,10 +139,8 @@ public class OpenPersistenceManagerInViewFilter extends OncePerRequestFilter {
logger.debug("Using PersistenceManagerFactory '" + getPersistenceManagerFactoryBeanName() +
"' for OpenPersistenceManagerInViewFilter");
}
- WebApplicationContext wac =
- WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
- return (PersistenceManagerFactory)
- wac.getBean(getPersistenceManagerFactoryBeanName(), PersistenceManagerFactory.class);
+ WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
+ return wac.getBean(getPersistenceManagerFactoryBeanName(), PersistenceManagerFactory.class);
}
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/SpringPersistenceManagerProxyBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/SpringPersistenceManagerProxyBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..4188558833fbdadf7e9a979dc1950b6c2d1a9c6d
--- /dev/null
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/SpringPersistenceManagerProxyBean.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2002-2009 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.jdo.support;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.orm.jdo.JdoAccessor;
+import org.springframework.orm.jdo.PersistenceManagerFactoryUtils;
+import org.springframework.util.Assert;
+
+/**
+ * Proxy that implements the {@link javax.jdo.PersistenceManager} interface,
+ * delegating to the current thread-bound PersistenceManager (the Spring-managed
+ * transactional PersistenceManager or the single OpenPersistenceManagerInView
+ * PersistenceManager, if any) on each invocation. This class makes such a
+ * Spring-style PersistenceManager proxy available for bean references.
+ *
+ * The main advantage of this proxy is that it allows DAOs to work with a
+ * plain JDO PersistenceManager reference in JDO 2.1 style
+ * (see {@link javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()}),
+ * while still participating in Spring's resource and transaction management.
+ *
+ *
The behavior of this proxy matches the behavior that the JDO 2.1 spec
+ * defines for a PersistenceManager proxy. Hence, DAOs could seamlessly switch
+ * between {@link StandardPersistenceManagerProxyBean} and this Spring-style proxy,
+ * receiving the reference through Dependency Injection. This will work without
+ * any Spring API dependencies in the DAO code!
+ *
+ *
Note: In contrast to {@link StandardPersistenceManagerProxyBean}, this proxy
+ * works with JDO 2.0 and higher. It does not require JDO 2.1.
+ *
+ * @author Juergen Hoeller
+ * @since 3.0
+ * @see StandardPersistenceManagerProxyBean
+ * @see javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()
+ * @see org.springframework.orm.jdo.PersistenceManagerFactoryUtils#getPersistenceManager
+ * @see org.springframework.orm.jdo.PersistenceManagerFactoryUtils#releasePersistenceManager
+ */
+public class SpringPersistenceManagerProxyBean extends JdoAccessor implements FactoryBean {
+
+ private Class extends PersistenceManager> persistenceManagerInterface = PersistenceManager.class;
+
+ private boolean allowCreate = true;
+
+ private PersistenceManager proxy;
+
+
+ /**
+ * Specify the PersistenceManager interface to expose,
+ * possibly including vendor extensions.
+ * Default is the standard javax.jdo.PersistenceManager
interface.
+ */
+ public void setPersistenceManagerInterface(Class extends PersistenceManager> persistenceManagerInterface) {
+ this.persistenceManagerInterface = persistenceManagerInterface;
+ Assert.notNull(persistenceManagerInterface, "persistenceManagerInterface must not be null");
+ Assert.isAssignable(PersistenceManager.class, persistenceManagerInterface);
+ }
+
+ /**
+ * Return the PersistenceManager interface to expose.
+ */
+ protected Class extends PersistenceManager> getPersistenceManagerInterface() {
+ return this.persistenceManagerInterface;
+ }
+
+ /**
+ * Set whether the PersistenceManagerFactory proxy is allowed to create
+ * a non-transactional PersistenceManager when no transactional
+ * PersistenceManager can be found for the current thread.
+ *
Default is "true". Can be turned off to enforce access to
+ * transactional PersistenceManagers, which safely allows for DAOs
+ * written to get a PersistenceManager without explicit closing
+ * (i.e. a PersistenceManagerFactory.getPersistenceManager()
+ * call without corresponding PersistenceManager.close()
call).
+ * @see org.springframework.orm.jdo.PersistenceManagerFactoryUtils#getPersistenceManager(javax.jdo.PersistenceManagerFactory, boolean)
+ */
+ public void setAllowCreate(boolean allowCreate) {
+ this.allowCreate = allowCreate;
+ }
+
+ /**
+ * Return whether the PersistenceManagerFactory proxy is allowed to create
+ * a non-transactional PersistenceManager when no transactional
+ * PersistenceManager can be found for the current thread.
+ */
+ protected boolean isAllowCreate() {
+ return this.allowCreate;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ super.afterPropertiesSet();
+ this.proxy = (PersistenceManager) Proxy.newProxyInstance(
+ getPersistenceManagerFactory().getClass().getClassLoader(),
+ new Class[] {getPersistenceManagerInterface()}, new PersistenceManagerInvocationHandler());
+ }
+
+
+ public PersistenceManager getObject() {
+ return this.proxy;
+ }
+
+ public Class extends PersistenceManager> getObjectType() {
+ return getPersistenceManagerInterface();
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+
+ /**
+ * Invocation handler that delegates close calls on PersistenceManagers to
+ * PersistenceManagerFactoryUtils for being aware of thread-bound transactions.
+ */
+ private class PersistenceManagerInvocationHandler implements InvocationHandler {
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ // Invocation on PersistenceManager interface coming in...
+
+ if (method.getName().equals("equals")) {
+ // Only consider equal when proxies are identical.
+ return (proxy == args[0]);
+ }
+ else if (method.getName().equals("hashCode")) {
+ // Use hashCode of PersistenceManager proxy.
+ return System.identityHashCode(proxy);
+ }
+ else if (method.getName().equals("toString")) {
+ // Deliver toString without touching a target EntityManager.
+ return "Spring PersistenceManager proxy for target factory [" + getPersistenceManagerFactory() + "]";
+ }
+ else if (method.getName().equals("getPersistenceManagerFactory")) {
+ // Return PersistenceManagerFactory without creating a PersistenceManager.
+ return getPersistenceManagerFactory();
+ }
+ else if (method.getName().equals("isClosed")) {
+ // Proxy is always usable.
+ return false;
+ }
+ else if (method.getName().equals("close")) {
+ // Suppress close method.
+ return null;
+ }
+
+ // Invoke method on target PersistenceManager.
+ PersistenceManager pm = PersistenceManagerFactoryUtils.doGetPersistenceManager(
+ getPersistenceManagerFactory(), isAllowCreate());
+ try {
+ Object retVal = method.invoke(pm, args);
+ if (retVal instanceof Query) {
+ PersistenceManagerFactoryUtils.applyTransactionTimeout(
+ (Query) retVal, getPersistenceManagerFactory(), getJdoDialect());
+ }
+ return retVal;
+ }
+ catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ finally {
+ PersistenceManagerFactoryUtils.doReleasePersistenceManager(pm, getPersistenceManagerFactory());
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/StandardPersistenceManagerProxyBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/StandardPersistenceManagerProxyBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..835642d3d5c7f367af502ea26154b2c671964e6f
--- /dev/null
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jdo/support/StandardPersistenceManagerProxyBean.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2009 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 exprShess or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.jdo.support;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.util.Assert;
+
+/**
+ * Proxy that implements the {@link javax.jdo.PersistenceManager} interface,
+ * delegating to a thread-bound PersistenceManager on each invocation -
+ * as defined by the JDO 2.1 specification. This class makes such a standard
+ * JDO PersistenceManager proxy available for bean references.
+ *
+ *
The main advantage of this proxy is that it allows DAOs to work with a
+ * plain JDO PersistenceManager reference in JDO 2.1 style
+ * (see {@link javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()}),
+ * exposing the exact behavior that the target JDO provider implements.
+ *
+ *
Note: This proxy requires JDO 2.1 or higher.
+ *
+ * @author Juergen Hoeller
+ * @since 3.0
+ * @see SpringPersistenceManagerProxyBean
+ * @see javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()
+ */
+public class StandardPersistenceManagerProxyBean implements FactoryBean {
+
+ private PersistenceManager proxy;
+
+
+ /**
+ * Set the target JDO PersistenceManagerFactory that this proxy should
+ * delegate to. This should be the raw PersistenceManagerFactory, as
+ * accessed by JdoTransactionManager.
+ * @see org.springframework.orm.jdo.JdoTransactionManager
+ */
+ public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
+ Assert.notNull(pmf, "PersistenceManagerFactory must not be null");
+ this.proxy = pmf.getPersistenceManagerProxy();
+ }
+
+
+ public PersistenceManager getObject() {
+ return this.proxy;
+ }
+
+ public Class extends PersistenceManager> getObjectType() {
+ return (this.proxy != null ? this.proxy.getClass() : PersistenceManager.class);
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java
index b355813a608a2653b00138230ad49cbd6626b5cf..52e1fb01c4fade429063b26f13490f93cad22515 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -73,7 +73,7 @@ import org.springframework.util.CollectionUtils;
* @see LocalContainerEntityManagerFactoryBean
*/
public abstract class AbstractEntityManagerFactoryBean implements
- FactoryBean, BeanClassLoaderAware, InitializingBean, DisposableBean,
+ FactoryBean, BeanClassLoaderAware, InitializingBean, DisposableBean,
EntityManagerFactoryInfo, PersistenceExceptionTranslator {
/** Logger available to subclasses */
@@ -370,7 +370,7 @@ public abstract class AbstractEntityManagerFactoryBean implements
return this.entityManagerFactory;
}
- public Class getObjectType() {
+ public Class extends EntityManagerFactory> getObjectType() {
return (this.entityManagerFactory != null ? this.entityManagerFactory.getClass() : EntityManagerFactory.class);
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java
index a343973c8a45888854be6bc1f2bee238a8335d7b..e5b2f64e144e27a41a97494db8f696765af5c858 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java
@@ -17,7 +17,6 @@
package org.springframework.orm.jpa;
import java.util.Map;
-
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
@@ -26,6 +25,7 @@ import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
+import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;
import org.apache.commons.logging.Log;
@@ -248,6 +248,22 @@ public abstract class EntityManagerFactoryUtils {
}
}
+ /**
+ * Apply the current transaction timeout, if any, to the given JPA Query object.
+ * This method sets the JPA 2.0 query hints "javax.persistence.lock.timeout"
+ * and "javax.persistence.query.timeout" accordingly.
+ * @param query the JPA Query object
+ * @param emf JPA EntityManagerFactory that the Query was created for
+ */
+ public static void applyTransactionTimeout(Query query, EntityManagerFactory emf) {
+ EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf);
+ if (emHolder != null && emHolder.hasTimeout()) {
+ int timeoutValue = emHolder.getTimeToLiveInSeconds();
+ query.setHint("javax.persistence.lock.timeout", timeoutValue);
+ query.setHint("javax.persistence.query.timeout", timeoutValue);
+ }
+ }
+
/**
* Convert the given runtime exception to an appropriate exception from the
* org.springframework.dao
hierarchy.
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java
index 109aa649a8a07c8e535f94a86cfdad908f6a3c09..cb5eb1a08cfe535dc2545d54c08b4e95c7d37952 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/ExtendedEntityManagerCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import java.lang.reflect.Proxy;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
-
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
@@ -294,7 +293,7 @@ public abstract class ExtendedEntityManagerCreator {
this.target = target;
this.plusOperations = plusOperations;
this.exceptionTranslator = exceptionTranslator;
- this.jta = (jta != null ? jta.booleanValue() : isJtaEntityManager());
+ this.jta = (jta != null ? jta : isJtaEntityManager());
this.containerManaged = containerManaged;
}
@@ -321,8 +320,16 @@ public abstract class ExtendedEntityManagerCreator {
return hashCode();
}
else if (method.getName().equals("getTargetEntityManager")) {
+ // Handle EntityManagerProxy interface.
return this.target;
}
+ else if (method.getName().equals("unwrap")) {
+ // Handle JPA 2.0 unwrap method - could be a proxy match.
+ Class targetClass = (Class) args[0];
+ if (targetClass == null || targetClass.isInstance(proxy)) {
+ return proxy;
+ }
+ }
else if (method.getName().equals("isOpen")) {
if (this.containerManaged) {
return true;
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaAccessor.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaAccessor.java
index ee265ace0dd8be1fdd4e91555579b045fd6f45fa..1cb88c01283f4f66858b4f1d0d14554e7b513a45 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaAccessor.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaAccessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -112,7 +112,7 @@ public abstract class JpaAccessor extends EntityManagerFactoryAccessor implement
public void afterPropertiesSet() {
EntityManagerFactory emf = getEntityManagerFactory();
if (emf == null && getEntityManager() == null) {
- throw new IllegalArgumentException("entityManagerFactory or entityManager is required");
+ throw new IllegalArgumentException("'entityManagerFactory' or 'entityManager' is required");
}
if (emf instanceof EntityManagerFactoryInfo) {
JpaDialect jpaDialect = ((EntityManagerFactoryInfo) emf).getJpaDialect();
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaCallback.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaCallback.java
index 42fef7fad5b59cd1ef257dfad55b59f8317cb24d..deaab1e22ebaa08e9b6f086e132565225f7160ab 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaCallback.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -30,7 +30,7 @@ import javax.persistence.PersistenceException;
* @see org.springframework.orm.jpa.JpaTemplate
* @see org.springframework.orm.jpa.JpaTransactionManager
*/
-public interface JpaCallback {
+public interface JpaCallback {
/**
* Gets called by JpaTemplate.execute
with an active
@@ -53,6 +53,6 @@ public interface JpaCallback {
* @see org.springframework.orm.jpa.JpaTemplate#execute
* @see org.springframework.orm.jpa.JpaTemplate#executeFind
*/
- Object doInJpa(EntityManager em) throws PersistenceException;
+ T doInJpa(EntityManager em) throws PersistenceException;
}
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaOperations.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaOperations.java
index 5ce389922a95a5d707771e67c203f2312dd363cb..321b4c167c183b89f3b85c3c0597bab1c9f21bba 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaOperations.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaOperations.java
@@ -49,9 +49,9 @@ import org.springframework.dao.DataAccessException;
*/
public interface JpaOperations {
- Object execute(JpaCallback action) throws DataAccessException;
+ T execute(JpaCallback action) throws DataAccessException;
- List executeFind(JpaCallback action) throws DataAccessException;
+ List executeFind(JpaCallback> action) throws DataAccessException;
T find(Class entityClass, Object id) throws DataAccessException;
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaTemplate.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaTemplate.java
index d326591a23cbd55aee9b829532e3f52cf7f22775..79727cea83e9544a6480afc4d0b60ddf233f87d3 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaTemplate.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/JpaTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -22,7 +22,6 @@ 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;
@@ -143,11 +142,11 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
- public Object execute(JpaCallback action) throws DataAccessException {
+ public T execute(JpaCallback action) throws DataAccessException {
return execute(action, isExposeNativeEntityManager());
}
- public List executeFind(JpaCallback action) throws DataAccessException {
+ public List executeFind(JpaCallback> action) throws DataAccessException {
Object result = execute(action, isExposeNativeEntityManager());
if (!(result instanceof List)) {
throw new InvalidDataAccessApiUsageException(
@@ -165,7 +164,7 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
* @return a result object returned by the action, or null
* @throws org.springframework.dao.DataAccessException in case of JPA errors
*/
- public Object execute(JpaCallback action, boolean exposeNativeEntityManager) throws DataAccessException {
+ public T execute(JpaCallback action, boolean exposeNativeEntityManager) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
EntityManager em = getEntityManager();
@@ -181,7 +180,7 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
try {
EntityManager emToExpose = (exposeNativeEntityManager ? em : createEntityManagerProxy(em));
- Object result = action.doInJpa(emToExpose);
+ T result = action.doInJpa(emToExpose);
flushIfNecessary(em, !isNewEm);
return result;
}
@@ -226,35 +225,32 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
// Convenience methods for load, save, delete
//-------------------------------------------------------------------------
- @SuppressWarnings("unchecked")
public T find(final Class entityClass, final Object id) throws DataAccessException {
- return (T) execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public T doInJpa(EntityManager em) throws PersistenceException {
return em.find(entityClass, id);
}
}, true);
}
- @SuppressWarnings("unchecked")
public T getReference(final Class entityClass, final Object id) throws DataAccessException {
- return (T) execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public T doInJpa(EntityManager em) throws PersistenceException {
return em.getReference(entityClass, id);
}
}, true);
}
public boolean contains(final Object entity) throws DataAccessException {
- Boolean result = (Boolean) execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public Boolean doInJpa(EntityManager em) throws PersistenceException {
return em.contains(entity);
}
}, true);
- return result;
}
public void refresh(final Object entity) throws DataAccessException {
- execute(new JpaCallback() {
+ execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
em.refresh(entity);
return null;
@@ -263,7 +259,7 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public void persist(final Object entity) throws DataAccessException {
- execute(new JpaCallback() {
+ execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
em.persist(entity);
return null;
@@ -271,17 +267,16 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}, true);
}
- @SuppressWarnings("unchecked")
public T merge(final T entity) throws DataAccessException {
- return (T) execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public T doInJpa(EntityManager em) throws PersistenceException {
return em.merge(entity);
}
}, true);
}
public void remove(final Object entity) throws DataAccessException {
- execute(new JpaCallback() {
+ execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
em.remove(entity);
return null;
@@ -290,7 +285,7 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public void flush() throws DataAccessException {
- execute(new JpaCallback() {
+ execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
em.flush();
return null;
@@ -308,9 +303,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public List find(final String queryString, final Object... values) throws DataAccessException {
- return executeFind(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ 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]);
@@ -322,9 +318,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public List findByNamedParams(final String queryString, final Map params) throws DataAccessException {
- return executeFind(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public List doInJpa(EntityManager em) throws PersistenceException {
Query queryObject = em.createQuery(queryString);
+ prepareQuery(queryObject);
if (params != null) {
for (Map.Entry entry : params.entrySet()) {
queryObject.setParameter(entry.getKey(), entry.getValue());
@@ -340,9 +337,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public List findByNamedQuery(final String queryName, final Object... values) throws DataAccessException {
- return executeFind(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ 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]);
@@ -356,9 +354,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
public List findByNamedQueryAndNamedParams(final String queryName, final Map params)
throws DataAccessException {
- return executeFind(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
+ return execute(new JpaCallback() {
+ public List doInJpa(EntityManager em) throws PersistenceException {
Query queryObject = em.createNamedQuery(queryName);
+ prepareQuery(queryObject);
if (params != null) {
for (Map.Entry entry : params.entrySet()) {
queryObject.setParameter(entry.getKey(), entry.getValue());
@@ -370,10 +369,32 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
+ /**
+ * Prepare the given JPA query object. To be used within a JpaCallback.
+ * Applies a transaction timeout, if any. If you don't use such timeouts,
+ * the call is a no-op.
+ *
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 and Criteria objects.
- * @see javax.persistence.EntityManager#close
+ * Also prepares returned Query objects.
+ * @see javax.persistence.EntityManager#close()
*/
private class CloseSuppressingInvocationHandler implements InvocationHandler {
@@ -401,7 +422,12 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
// Invoke method on target EntityManager.
try {
- return method.invoke(this.target, args);
+ 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();
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java
index 1e835850eeda8a2e897f0a711f686dd4c30bb340..46dd61687301044389b54deace51ea37d7277a59 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -21,7 +21,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
-
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
@@ -151,6 +150,26 @@ public abstract class SharedEntityManagerCreator {
// Deliver toString without touching a target EntityManager.
return "Shared EntityManager proxy for target factory [" + this.targetFactory + "]";
}
+ else if (method.getName().equals("getEntityManagerFactory")) {
+ // JPA 2.0: return EntityManagerFactory without creating an EntityManager.
+ return this.targetFactory;
+ }
+ else if (method.getName().equals("getQueryBuilder")) {
+ // JPA 2.0: return EntityManagerFactory's QueryBuilder (avoid creation of EntityManager).
+ try {
+ return EntityManagerFactory.class.getMethod("getQueryBuilder").invoke(this.targetFactory);
+ }
+ catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+ else if (method.getName().equals("unwrap")) {
+ // JPA 2.0: handle unwrap method - could be a proxy match.
+ Class targetClass = (Class) args[0];
+ if (targetClass == null || targetClass.isInstance(proxy)) {
+ return proxy;
+ }
+ }
else if (method.getName().equals("isOpen")) {
// Handle isOpen method: always return true.
return true;
@@ -175,13 +194,24 @@ public abstract class SharedEntityManagerCreator {
EntityManager target =
EntityManagerFactoryUtils.doGetTransactionalEntityManager(this.targetFactory, this.properties);
- // Handle EntityManagerProxy interface.
if (method.getName().equals("getTargetEntityManager")) {
+ // Handle EntityManagerProxy interface.
if (target == null) {
throw new IllegalStateException("No transactional EntityManager available");
}
return target;
}
+ else if (method.getName().equals("unwrap")) {
+ // Handle JPA 2.0 unwrap method - could be a proxy match.
+ Class targetClass = (Class) args[0];
+ if (targetClass == null || targetClass.isInstance(proxy)) {
+ return proxy;
+ }
+ // We need a transactional target now.
+ if (target == null) {
+ throw new IllegalStateException("No transactional EntityManager available");
+ }
+ }
// Regular EntityManager operations.
boolean isNewEm = false;
@@ -196,10 +226,16 @@ public abstract class SharedEntityManagerCreator {
// Invoke method on current EntityManager.
try {
Object result = method.invoke(target, args);
- if (isNewEm && result instanceof Query) {
- result = Proxy.newProxyInstance(Query.class.getClassLoader(), new Class[] {Query.class},
- new DeferredQueryInvocationHandler((Query) result, target));
- isNewEm = false;
+ if (result instanceof Query) {
+ Query query = (Query) result;
+ if (isNewEm) {
+ result = Proxy.newProxyInstance(Query.class.getClassLoader(), new Class[] {Query.class},
+ new DeferredQueryInvocationHandler(query, target));
+ isNewEm = false;
+ }
+ else {
+ EntityManagerFactoryUtils.applyTransactionTimeout(query, this.targetFactory);
+ }
}
return result;
}
@@ -241,6 +277,13 @@ public abstract class SharedEntityManagerCreator {
// Use hashCode of EntityManager proxy.
return hashCode();
}
+ else if (method.getName().equals("unwrap")) {
+ // Handle JPA 2.0 unwrap method - could be a proxy match.
+ Class targetClass = (Class) args[0];
+ if (targetClass == null || targetClass.isInstance(proxy)) {
+ return proxy;
+ }
+ }
// Invoke method on actual Query object.
try {
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
index 56de437c88da9fc1b7de5d848086ff1b54029268..3732ebb3d2ad1f64f520ecae897908a1bea46d8a 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -147,10 +147,8 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
logger.debug("Using EntityManagerFactory '" + getEntityManagerFactoryBeanName() +
"' for OpenEntityManagerInViewFilter");
}
- WebApplicationContext wac =
- WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
- return (EntityManagerFactory)
- wac.getBean(getEntityManagerFactoryBeanName(), EntityManagerFactory.class);
+ WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
+ return wac.getBean(getEntityManagerFactoryBeanName(), EntityManagerFactory.class);
}
/**
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
index 3ba4a0d35e35b6ac7408f9eb2dd962769c382439..e443f42aca00cc306e8872f8fbdab3275c95f38b 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -26,7 +26,6 @@ import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
-
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
@@ -405,7 +404,7 @@ public class PersistenceAnnotationBeanPostProcessor extends JndiLocatorSupport
}
if (jndiName != null) {
try {
- return (EntityManagerFactory) lookup(jndiName, EntityManagerFactory.class);
+ return lookup(jndiName, EntityManagerFactory.class);
}
catch (NamingException ex) {
throw new IllegalStateException("Could not obtain EntityManagerFactory [" + jndiName + "] from JNDI", ex);
@@ -437,7 +436,7 @@ public class PersistenceAnnotationBeanPostProcessor extends JndiLocatorSupport
}
if (jndiName != null) {
try {
- return (EntityManager) lookup(jndiName, EntityManager.class);
+ return lookup(jndiName, EntityManager.class);
}
catch (NamingException ex) {
throw new IllegalStateException("Could not obtain EntityManager [" + jndiName + "] from JNDI", ex);
diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/SharedEntityManagerBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/SharedEntityManagerBean.java
index 5d865c63f9d5f90ec4d94a9d408da90e38552c5d..d2289c53289b589a5f70aa26a8d2f41f0d778389 100644
--- a/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/SharedEntityManagerBean.java
+++ b/org.springframework.orm/src/main/java/org/springframework/orm/jpa/support/SharedEntityManagerBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -50,22 +50,23 @@ import org.springframework.util.Assert;
* @see org.springframework.orm.jpa.LocalEntityManagerFactoryBean
* @see org.springframework.orm.jpa.JpaTransactionManager
*/
-public class SharedEntityManagerBean extends EntityManagerFactoryAccessor implements FactoryBean, InitializingBean {
+public class SharedEntityManagerBean extends EntityManagerFactoryAccessor
+ implements FactoryBean, InitializingBean {
- private Class entityManagerInterface;
+ private Class extends EntityManager> entityManagerInterface;
private EntityManager shared;
/**
* Specify the EntityManager interface to expose.
- * Default is the the EntityManager interface as defined by the
+ *
Default is the EntityManager interface as defined by the
* EntityManagerFactoryInfo, if available. Else, the standard
* javax.persistence.EntityManager
interface will be used.
* @see org.springframework.orm.jpa.EntityManagerFactoryInfo#getEntityManagerInterface()
* @see javax.persistence.EntityManager
*/
- public void setEntityManagerInterface(Class entityManagerInterface) {
+ public void setEntityManagerInterface(Class extends EntityManager> entityManagerInterface) {
Assert.notNull(entityManagerInterface, "entityManagerInterface must not be null");
Assert.isAssignable(EntityManager.class, entityManagerInterface);
this.entityManagerInterface = entityManagerInterface;
@@ -108,8 +109,8 @@ public class SharedEntityManagerBean extends EntityManagerFactoryAccessor implem
return this.shared;
}
- public Class getObjectType() {
- return this.entityManagerInterface;
+ public Class extends EntityManager> getObjectType() {
+ return (this.entityManagerInterface != null ? this.entityManagerInterface : EntityManager.class);
}
public boolean isSingleton() {
diff --git a/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java b/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java
index a0c5f020fa377b269ff17e24334d6586ad1a2dd5..5ac6d360421c8be70fca97f3c860276a0e3c116f 100644
--- a/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java
+++ b/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -22,7 +22,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-
import javax.jdo.JDODataStoreException;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalDataStoreException;
@@ -125,17 +124,12 @@ public class JdoTemplateTests extends TestCase {
}
public void testTemplateExecuteWithThreadBoundAndFlushEager() {
- MockControl dialectControl = MockControl.createControl(JdoDialect.class);
- JdoDialect dialect = (JdoDialect) dialectControl.getMock();
-
- dialect.flush(pm);
- dialectControl.setVoidCallable(1);
+ pm.flush();
+ pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
- dialectControl.replay();
JdoTemplate jt = new JdoTemplate(pmf);
- jt.setJdoDialect(dialect);
jt.setFlushEager(true);
jt.setAllowCreate(false);
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
@@ -148,7 +142,6 @@ public class JdoTemplateTests extends TestCase {
});
assertTrue("Correct result list", result == l);
TransactionSynchronizationManager.unbindResource(pmf);
- dialectControl.verify();
}
public void testGetObjectById() {
@@ -373,23 +366,17 @@ public class JdoTemplateTests extends TestCase {
}
public void testFlushWithDialect() {
- MockControl dialectControl = MockControl.createControl(JdoDialect.class);
- JdoDialect dialect = (JdoDialect) dialectControl.getMock();
-
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm);
- dialect.flush(pm);
- dialectControl.setVoidCallable(1);
+ pm.flush();
+ pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
- dialectControl.replay();
JdoTemplate jt = new JdoTemplate(pmf);
- jt.setJdoDialect(dialect);
jt.flush();
- dialectControl.verify();
}
public void testFind() {
diff --git a/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java b/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java
index 0294cfcee57c7c5d7a87e35bb6f2fecf0913125b..4591a7187ec8910fba94f4fe640adf213fde1fc5 100644
--- a/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java
+++ b/org.springframework.orm/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java
@@ -23,7 +23,6 @@ import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.List;
-
import javax.jdo.JDOFatalDataStoreException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
@@ -41,6 +40,8 @@ import org.springframework.beans.TestBean;
import org.springframework.jdbc.datasource.ConnectionHandle;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.SimpleConnectionHandle;
+import org.springframework.orm.jdo.support.SpringPersistenceManagerProxyBean;
+import org.springframework.orm.jdo.support.StandardPersistenceManagerProxyBean;
import org.springframework.transaction.InvalidIsolationLevelException;
import org.springframework.transaction.MockJtaTransaction;
import org.springframework.transaction.PlatformTransactionManager;
@@ -93,13 +94,15 @@ public class JdoTransactionManagerTests extends TestCase {
public void testTransactionCommit() {
pmf.getConnectionFactory();
- pmfControl.setReturnValue(null, 2);
+ pmfControl.setReturnValue(null, 3);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
+ pmf.getPersistenceManagerProxy();
+ pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.flush();
- pmControl.setVoidCallable(2);
+ pmControl.setVoidCallable(4);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
@@ -126,10 +129,23 @@ public class JdoTransactionManagerTests extends TestCase {
TransactionAwarePersistenceManagerFactoryProxy proxyFactory =
new TransactionAwarePersistenceManagerFactoryProxy();
proxyFactory.setTargetPersistenceManagerFactory(pmf);
- PersistenceManagerFactory proxy = (PersistenceManagerFactory) proxyFactory.getObject();
- assertEquals(pm.toString(), proxy.getPersistenceManager().toString());
- proxy.getPersistenceManager().flush();
- proxy.getPersistenceManager().close();
+ PersistenceManagerFactory pmfProxy = proxyFactory.getObject();
+ assertEquals(pm.toString(), pmfProxy.getPersistenceManager().toString());
+ pmfProxy.getPersistenceManager().flush();
+ pmfProxy.getPersistenceManager().close();
+
+ SpringPersistenceManagerProxyBean proxyBean = new SpringPersistenceManagerProxyBean();
+ proxyBean.setPersistenceManagerFactory(pmf);
+ proxyBean.afterPropertiesSet();
+ PersistenceManager pmProxy = proxyBean.getObject();
+ assertSame(pmf, pmProxy.getPersistenceManagerFactory());
+ pmProxy.flush();
+ pmProxy.close();
+
+ StandardPersistenceManagerProxyBean stdProxyBean = new StandardPersistenceManagerProxyBean();
+ stdProxyBean.setPersistenceManagerFactory(pmf);
+ PersistenceManager stdPmProxy = stdProxyBean.getObject();
+ stdPmProxy.flush();
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {