提交 e7465dcb 编写于 作者: J Juergen Hoeller

generified operations interfaces; update to JDO 2.1; preparation for JPA 2.0

上级 612ed8c6
......@@ -47,7 +47,7 @@
<dependency org="org.hibernate" name="com.springsource.org.hibernate" rev="3.2.6.ga" conf="optional, hibernate->compile"/>
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="optional, hibernate-jpa->compile"/>
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="optional, hibernate-jpa->compile"/>
<dependency org="javax.jdo" name="com.springsource.javax.jdo" rev="2.0.0" conf="provided, jdo->compile"/>
<dependency org="javax.jdo" name="com.springsource.javax.jdo" rev="2.1.0" conf="provided, jdo->compile"/>
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="provided, jpa->compile"/>
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.5.0" conf="provided, web->compile"/>
<dependency org="javax.transaction" name="com.springsource.javax.transaction" rev="1.1.0" conf="provided->runtime"/>
......
......@@ -162,11 +162,11 @@
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$IVY_CACHE$/javax.jdo/com.springsource.javax.jdo/2.0.0/com.springsource.javax.jdo-2.0.0.jar!/" />
<root url="jar://$IVY_CACHE$/javax.jdo/com.springsource.javax.jdo/2.1.0/com.springsource.javax.jdo-2.1.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$IVY_CACHE$/javax.jdo/com.springsource.javax.jdo/2.0.0/com.springsource.javax.jdo-sources-2.0.0.jar!/" />
<root url="jar://$IVY_CACHE$/javax.jdo/com.springsource.javax.jdo/2.1.0/com.springsource.javax.jdo-sources-2.1.0.jar!/" />
</SOURCES>
</library>
</orderEntry>
......
/*
* 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.
......@@ -55,7 +55,7 @@ import org.springframework.jdbc.support.SQLExceptionTranslator;
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
*/
public abstract class AbstractSessionFactoryBean
implements FactoryBean, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
implements FactoryBean<SessionFactory>, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
......@@ -256,11 +256,11 @@ public abstract class AbstractSessionFactoryBean
/**
* Return the singleton SessionFactory.
*/
public Object getObject() {
public SessionFactory getObject() {
return this.sessionFactory;
}
public Class getObjectType() {
public Class<? extends SessionFactory> getObjectType() {
return (this.sessionFactory != null) ? this.sessionFactory.getClass() : SessionFactory.class;
}
......
/*
* 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 org.hibernate.Session;
* @see HibernateTemplate
* @see HibernateTransactionManager
*/
public interface HibernateCallback {
public interface HibernateCallback<T> {
/**
* Gets called by <code>HibernateTemplate.execute</code> with an active
......@@ -66,6 +66,6 @@ public interface HibernateCallback {
* @see HibernateTemplate#execute
* @see HibernateTemplate#executeFind
*/
Object doInHibernate(Session session) throws HibernateException, SQLException;
T doInHibernate(Session session) throws HibernateException, SQLException;
}
/*
* 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.
......@@ -85,7 +85,7 @@ public interface HibernateOperations {
* @see org.springframework.transaction
* @see org.hibernate.Session
*/
Object execute(HibernateCallback action) throws DataAccessException;
<T> T execute(HibernateCallback<T> action) throws DataAccessException;
/**
* Execute the specified action assuming that the result object is a
......@@ -96,7 +96,7 @@ public interface HibernateOperations {
* @return a List result returned by the action, or <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
List executeFind(HibernateCallback action) throws DataAccessException;
List executeFind(HibernateCallback<?> action) throws DataAccessException;
//-------------------------------------------------------------------------
......@@ -530,7 +530,7 @@ public interface HibernateOperations {
* @see org.hibernate.Session#merge(String, Object)
* @see #saveOrUpdate
*/
Object merge(String entityName, Object entity) throws DataAccessException;
<T> T merge(String entityName, T entity) throws DataAccessException;
/**
* Delete the given persistent instance.
......
......@@ -360,7 +360,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
}
String beanName = (String) this.entityInterceptor;
return (Interceptor) this.beanFactory.getBean(beanName, Interceptor.class);
return this.beanFactory.getBean(beanName, Interceptor.class);
}
else {
return null;
......
/*
* 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.
......@@ -17,7 +17,6 @@
package org.springframework.orm.hibernate3.support;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
......@@ -239,9 +238,8 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
if (logger.isDebugEnabled()) {
logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
}
WebApplicationContext wac =
WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return (SessionFactory) wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
}
/**
......
/*
* 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.io.InputStream;
import java.lang.reflect.Field;
import java.util.Properties;
import javax.sql.DataSource;
import com.ibatis.common.xml.NodeletException;
......@@ -68,7 +67,7 @@ import org.springframework.util.ObjectUtils;
* @see SqlMapClientTemplate#setSqlMapClient
* @see SqlMapClientTemplate#setDataSource
*/
public class SqlMapClientFactoryBean implements FactoryBean, InitializingBean {
public class SqlMapClientFactoryBean implements FactoryBean<SqlMapClient>, 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);
}
......
/*
* 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 <code>flush</code> method.
* <p>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);
}
......
/*
* 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();
}
}
......
/*
* 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<T> {
/**
* Gets called by <code>JdoTemplate.execute</code> 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;
}
/*
* 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.
* <p>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
*/
......
/*
* 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> T execute(JdoCallback<T> 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 <code>null</code>
* @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> T getObjectById(Class<T> 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> 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;
<T> Collection<T> makePersistentAll(Collection<T> 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> 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);
<T> Collection<T> detachCopyAll(Collection<T> 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;
<T> Collection<T> find(Class<T> 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;
<T> Collection<T> find(Class<T> 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;
<T> Collection<T> find(Class<T> 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)
<T> Collection<T> find(Class<T> 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)
<T> Collection<T> find(Class<T> 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)
<T> Collection<T> find(Class<T> 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)
<T> Collection<T> find(Class<T> 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;
<T> Collection<T> findByNamedQuery(Class<T> 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;
<T> Collection<T> findByNamedQuery(Class<T> 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;
<T> Collection<T> findByNamedQuery(Class<T> entityClass, String queryName, Map values)
throws DataAccessException;
}
/*
* 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: <code>evict</code>, <code>evictAll</code>, <code>flush</code>.
*
* <p><b>NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.</b>
* 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> T execute(JdoCallback<T> 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 <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of JDO errors
*/
public Object execute(JdoCallback action, boolean exposeNativePersistenceManager) throws DataAccessException {
public <T> T execute(JdoCallback<T> 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> 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<Object>() {
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> T getObjectById(final Class<T> entityClass, final Object idValue) throws DataAccessException {
return execute(new JdoCallback<T>() {
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<Object>() {
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<Object>() {
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<Object>() {
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<Object>() {
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<Object>() {
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<Object>() {
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> T makePersistent(final T entity) throws DataAccessException {
return execute(new JdoCallback<T>() {
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 <T> Collection<T> makePersistentAll(final Collection<T> entities) throws DataAccessException {
return execute(new JdoCallback<Collection<T>>() {
public Collection<T> doInJdo(PersistenceManager pm) throws JDOException {
return pm.makePersistentAll(entities);
}
}, true);
}
public void deletePersistent(final Object entity) throws DataAccessException {
execute(new JdoCallback() {
execute(new JdoCallback<Object>() {
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<Object>() {
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> T detachCopy(final T entity) {
return execute(new JdoCallback<T>() {
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 <T> Collection<T> detachCopyAll(final Collection<T> entities) {
return execute(new JdoCallback<Collection<T>>() {
public Collection<T> doInJdo(PersistenceManager pm) throws JDOException {
return pm.detachCopyAll(entities);
}
}, true);
}
public void flush() throws DataAccessException {
execute(new JdoCallback() {
execute(new JdoCallback<Object>() {
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 <T> Collection<T> find(Class<T> entityClass) throws DataAccessException {
return find(entityClass, null, null);
}
public Collection find(Class entityClass, String filter) throws DataAccessException {
public <T> Collection<T> find(Class<T> entityClass, String filter) throws DataAccessException {
return find(entityClass, filter, null);
}
public Collection find(final Class entityClass, final String filter, final String ordering)
public <T> Collection<T> find(final Class<T> 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<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> 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<T>) query.execute();
}
}, true);
}
public Collection find(Class entityClass, String filter, String parameters, Object[] values)
public <T> Collection<T> find(Class<T> 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 <T> Collection<T> find(
final Class<T> 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<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> 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<T>) query.executeWithArray(values);
}
}, true);
}
public Collection find(Class entityClass, String filter, String parameters, Map values)
public <T> Collection<T> find(Class<T> 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 <T> Collection<T> find(
final Class<T> 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<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> 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<T>) 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<Collection>() {
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<Collection>() {
@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<Collection>() {
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<Collection>() {
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 <T> Collection<T> findByNamedQuery(final Class<T> entityClass, final String queryName)
throws DataAccessException {
return execute(new JdoCallback<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
return query.execute();
return (Collection<T>) query.execute();
}
}, true);
}
public Collection findByNamedQuery(final Class entityClass, final String queryName, final Object[] values)
public <T> Collection<T> findByNamedQuery(final Class<T> 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<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
return query.executeWithArray(values);
return (Collection<T>) query.executeWithArray(values);
}
}, true);
}
public Collection findByNamedQuery(final Class entityClass, final String queryName, final Map values)
public <T> Collection<T> findByNamedQuery(final Class<T> 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<Collection<T>>() {
@SuppressWarnings("unchecked")
public Collection<T> doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newNamedQuery(entityClass, queryName);
prepareQuery(query);
return query.executeWithMap(values);
return (Collection<T>) 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,
* <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 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) {
......
/*
* 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!
*
* <p><b>NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.</b>
* 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.
*
* <p>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}).
*
* <p><b>NOTE: This class requires JDO 2.0 or higher, as of Spring 2.5.</b>
*
* <p>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<PersistenceManagerFactory>,
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);
}
......
/*
* 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.
......
/*
* 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 <code>getPersistenceManager()</code>, if any.
*
* <p>Essentially, <code>getPersistenceManager()</code> 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<PersistenceManagerFactory> {
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;
}
......
/*
* 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);
}
}
/*
* 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.
*
* <p>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.
*
* <p>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!
*
* <p>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<PersistenceManager> {
private Class<? extends PersistenceManager> persistenceManagerInterface = PersistenceManager.class;
private boolean allowCreate = true;
private PersistenceManager proxy;
/**
* Specify the PersistenceManager interface to expose,
* possibly including vendor extensions.
* <p>Default is the standard <code>javax.jdo.PersistenceManager</code> 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.
* <p>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 <code>PersistenceManagerFactory.getPersistenceManager()</code>
* call without corresponding <code>PersistenceManager.close()</code> 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());
}
}
}
}
/*
* 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.
*
* <p>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.
*
* <p>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<PersistenceManager> {
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;
}
}
/*
* 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<EntityManagerFactory>, 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);
}
......
......@@ -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.
* <p>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
* <code>org.springframework.dao</code> hierarchy.
......
/*
* 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;
......
/*
* 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();
......
/*
* 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<T> {
/**
* Gets called by <code>JpaTemplate.execute</code> 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;
}
......@@ -49,9 +49,9 @@ import org.springframework.dao.DataAccessException;
*/
public interface JpaOperations {
Object execute(JpaCallback action) throws DataAccessException;
<T> T execute(JpaCallback<T> action) throws DataAccessException;
List executeFind(JpaCallback action) throws DataAccessException;
List executeFind(JpaCallback<?> action) throws DataAccessException;
<T> T find(Class<T> entityClass, Object id) throws DataAccessException;
......
/*
* 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> T execute(JpaCallback<T> 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 <code>null</code>
* @throws org.springframework.dao.DataAccessException in case of JPA errors
*/
public Object execute(JpaCallback action, boolean exposeNativeEntityManager) throws DataAccessException {
public <T> T execute(JpaCallback<T> 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> T find(final Class<T> entityClass, final Object id) throws DataAccessException {
return (T) execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
return execute(new JpaCallback<T>() {
public T doInJpa(EntityManager em) throws PersistenceException {
return em.find(entityClass, id);
}
}, true);
}
@SuppressWarnings("unchecked")
public <T> T getReference(final Class<T> entityClass, final Object id) throws DataAccessException {
return (T) execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
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 {
Boolean result = (Boolean) execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
return execute(new JpaCallback<Boolean>() {
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<Object>() {
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<Object>() {
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> T merge(final T entity) throws DataAccessException {
return (T) execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
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() {
execute(new JpaCallback<Object>() {
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<Object>() {
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<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]);
......@@ -322,9 +318,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
public List findByNamedParams(final String queryString, final Map<String, ?> params) throws DataAccessException {
return executeFind(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
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());
......@@ -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<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]);
......@@ -356,9 +354,10 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
public List findByNamedQueryAndNamedParams(final String queryName, final Map<String, ?> params)
throws DataAccessException {
return executeFind(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
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());
......@@ -370,10 +369,32 @@ public class JpaTemplate extends JpaAccessor implements JpaOperations {
}
/**
* 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 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();
......
/*
* 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 {
......
/*
* 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);
}
/**
......
/*
* 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);
......
/*
* 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<EntityManager>, InitializingBean {
private Class entityManagerInterface;
private Class<? extends EntityManager> entityManagerInterface;
private EntityManager shared;
/**
* Specify the EntityManager interface to expose.
* <p>Default is the the EntityManager interface as defined by the
* <p>Default is the EntityManager interface as defined by the
* EntityManagerFactoryInfo, if available. Else, the standard
* <code>javax.persistence.EntityManager</code> 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() {
......
/*
* 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() {
......
......@@ -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() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册