diff --git a/org.springframework.orm/ivy.xml b/org.springframework.orm/ivy.xml index 8243d984a67e089305f40af59219be7c1c863f44..f7b51b37312859c93b0b92e05777abaf7614d9e0 100644 --- a/org.springframework.orm/ivy.xml +++ b/org.springframework.orm/ivy.xml @@ -47,7 +47,7 @@ - + diff --git a/org.springframework.orm/orm.iml b/org.springframework.orm/orm.iml index e89b1335bbff0c17676d9bd9b2192c7872cfffb8..2653f8e78ee46add0bb6322fe5b6087a86865268 100644 --- a/org.springframework.orm/orm.iml +++ b/org.springframework.orm/orm.iml @@ -162,11 +162,11 @@ - + - + diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java index 8e5acc85daedb2736a84b073e1d367c8ed015f56..32d1a152be7ce9c799708c4e9ea56c1329c965e6 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.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. @@ -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, 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 getObjectType() { return (this.sessionFactory != null) ? this.sessionFactory.getClass() : SessionFactory.class; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateCallback.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateCallback.java index 38846b7d238bfd59478a80278810e0935cba3a00..524b84da55c9cf15a50f62403865c0b8c17a2887 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateCallback.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateCallback.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 org.hibernate.Session; * @see HibernateTemplate * @see HibernateTransactionManager */ -public interface HibernateCallback { +public interface HibernateCallback { /** * Gets called by HibernateTemplate.execute 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; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateOperations.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateOperations.java index a18cc4167807b8cdff8fd5a01f3211969874321d..6d65c78eab06f4d09cba32424dc92605b503df39 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateOperations.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateOperations.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. @@ -85,7 +85,7 @@ public interface HibernateOperations { * @see org.springframework.transaction * @see org.hibernate.Session */ - Object execute(HibernateCallback action) throws DataAccessException; + T execute(HibernateCallback 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 null * @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 merge(String entityName, T entity) throws DataAccessException; /** * Delete the given persistent instance. diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java index 3b7b5e907a5c23afb521c6d4f0f00f0097dd4896..5025e17405998d95e9d00beeff5f8682e4c34a58 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java @@ -335,11 +335,11 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } - public Object execute(HibernateCallback action) throws DataAccessException { + public T execute(HibernateCallback action) throws DataAccessException { return doExecute(action, false, false); } - public List executeFind(HibernateCallback action) throws DataAccessException { + public List executeFind(HibernateCallback action) throws DataAccessException { Object result = doExecute(action, false, false); if (result != null && !(result instanceof List)) { throw new InvalidDataAccessApiUsageException( @@ -357,7 +357,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe * @return a result object returned by the action, or null * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ - public Object executeWithNewSession(HibernateCallback action) { + public T executeWithNewSession(HibernateCallback action) { return doExecute(action, true, false); } @@ -370,24 +370,10 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe * @return a result object returned by the action, or null * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ - public Object executeWithNativeSession(HibernateCallback action) { + public T executeWithNativeSession(HibernateCallback action) { return doExecute(action, false, true); } - /** - * Execute the action specified by the given action object within a Session. - * @param action callback object that specifies the Hibernate action - * @param enforceNativeSession whether to enforce exposure of the native - * Hibernate Session to callback code - * @return a result object returned by the action, or null - * @throws org.springframework.dao.DataAccessException in case of Hibernate errors - * @deprecated as of Spring 2.5, in favor of {@link #executeWithNativeSession} - */ - @Deprecated - public Object execute(HibernateCallback action, boolean enforceNativeSession) throws DataAccessException { - return doExecute(action, false, enforceNativeSession); - } - /** * Execute the action specified by the given action object within a Session. * @param action callback object that specifies the Hibernate action @@ -398,7 +384,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe * @return a result object returned by the action, or null * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ - protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession) + protected T doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); @@ -417,7 +403,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe enableFilters(session); Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); - Object result = action.doInHibernate(sessionToExpose); + T result = action.doInHibernate(sessionToExpose); flushIfNecessary(session, existingTransaction); return result; } @@ -520,17 +506,17 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe return get(entityClass, id, null); } - @SuppressWarnings("unchecked") public T get(final Class entityClass, final Serializable id, final LockMode lockMode) throws DataAccessException { - return (T) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + @SuppressWarnings("unchecked") + public T doInHibernate(Session session) throws HibernateException { if (lockMode != null) { - return session.get(entityClass, id, lockMode); + return (T) session.get(entityClass, id, lockMode); } else { - return session.get(entityClass, id); + return (T) session.get(entityClass, id); } } }); @@ -543,7 +529,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public Object get(final String entityName, final Serializable id, final LockMode lockMode) throws DataAccessException { - return executeWithNativeSession(new HibernateCallback() { + return executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { if (lockMode != null) { return session.get(entityName, id, lockMode); @@ -559,17 +545,17 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe return load(entityClass, id, null); } - @SuppressWarnings("unchecked") public T load(final Class entityClass, final Serializable id, final LockMode lockMode) throws DataAccessException { - return (T) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + @SuppressWarnings("unchecked") + public T doInHibernate(Session session) throws HibernateException { if (lockMode != null) { - return session.load(entityClass, id, lockMode); + return (T) session.load(entityClass, id, lockMode); } else { - return session.load(entityClass, id); + return (T) session.load(entityClass, id); } } }); @@ -582,7 +568,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public Object load(final String entityName, final Serializable id, final LockMode lockMode) throws DataAccessException { - return executeWithNativeSession(new HibernateCallback() { + return executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { if (lockMode != null) { return session.load(entityName, id, lockMode); @@ -594,10 +580,10 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe }); } - @SuppressWarnings("unchecked") public List loadAll(final Class entityClass) throws DataAccessException { - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback>() { + @SuppressWarnings("unchecked") + public List doInHibernate(Session session) throws HibernateException { Criteria criteria = session.createCriteria(entityClass); criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); prepareCriteria(criteria); @@ -607,7 +593,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void load(final Object entity, final Serializable id) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { session.load(entity, id); return null; @@ -620,7 +606,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void refresh(final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { if (lockMode != null) { session.refresh(entity, lockMode); @@ -634,15 +620,15 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public boolean contains(final Object entity) throws DataAccessException { - return (Boolean) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) { + return executeWithNativeSession(new HibernateCallback() { + public Boolean doInHibernate(Session session) { return session.contains(entity); } }); } public void evict(final Object entity) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { session.evict(entity); return null; @@ -674,7 +660,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe //------------------------------------------------------------------------- public void lock(final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { session.lock(entity, lockMode); return null; @@ -685,7 +671,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public void lock(final String entityName, final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { session.lock(entityName, entity, lockMode); return null; @@ -694,8 +680,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public Serializable save(final Object entity) throws DataAccessException { - return (Serializable) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public Serializable doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); return session.save(entity); } @@ -703,8 +689,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public Serializable save(final String entityName, final Object entity) throws DataAccessException { - return (Serializable) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public Serializable doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); return session.save(entityName, entity); } @@ -716,7 +702,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void update(final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.update(entity); @@ -735,7 +721,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public void update(final String entityName, final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.update(entityName, entity); @@ -748,7 +734,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void saveOrUpdate(final Object entity) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.saveOrUpdate(entity); @@ -758,7 +744,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void saveOrUpdate(final String entityName, final Object entity) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.saveOrUpdate(entityName, entity); @@ -768,7 +754,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void saveOrUpdateAll(final Collection entities) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); for (Object entity : entities) { @@ -782,7 +768,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public void replicate(final Object entity, final ReplicationMode replicationMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.replicate(entity, replicationMode); @@ -794,7 +780,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public void replicate(final String entityName, final Object entity, final ReplicationMode replicationMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.replicate(entityName, entity, replicationMode); @@ -804,7 +790,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void persist(final Object entity) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.persist(entity); @@ -814,7 +800,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void persist(final String entityName, final Object entity) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); session.persist(entityName, entity); @@ -823,20 +809,22 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe }); } - public Object merge(final Object entity) throws DataAccessException { - return executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + public T merge(final T entity) throws DataAccessException { + return executeWithNativeSession(new HibernateCallback() { + @SuppressWarnings("unchecked") + public T doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); - return session.merge(entity); + return (T) session.merge(entity); } }); } - public Object merge(final String entityName, final Object entity) throws DataAccessException { - return executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + public T merge(final String entityName, final T entity) throws DataAccessException { + return executeWithNativeSession(new HibernateCallback() { + @SuppressWarnings("unchecked") + public T doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); - return session.merge(entityName, entity); + return (T) session.merge(entityName, entity); } }); } @@ -846,7 +834,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void delete(final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); if (lockMode != null) { @@ -865,7 +853,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public void delete(final String entityName, final Object entity, final LockMode lockMode) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); if (lockMode != null) { @@ -878,7 +866,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void deleteAll(final Collection entities) throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); for (Object entity : entities) { @@ -890,7 +878,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void flush() throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { session.flush(); return null; @@ -899,7 +887,7 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public void clear() throws DataAccessException { - executeWithNativeSession(new HibernateCallback() { + executeWithNativeSession(new HibernateCallback() { public Object doInHibernate(Session session) { session.clear(); return null; @@ -921,8 +909,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public List find(final String queryString, final Object... values) throws DataAccessException { - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.createQuery(queryString); prepareQuery(queryObject); if (values != null) { @@ -947,8 +935,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe if (paramNames.length != values.length) { throw new IllegalArgumentException("Length of paramNames array must match length of values array"); } - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.createQuery(queryString); prepareQuery(queryObject); if (values != null) { @@ -964,8 +952,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public List findByValueBean(final String queryString, final Object valueBean) throws DataAccessException { - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.createQuery(queryString); prepareQuery(queryObject); queryObject.setProperties(valueBean); @@ -988,8 +976,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public List findByNamedQuery(final String queryName, final Object... values) throws DataAccessException { - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.getNamedQuery(queryName); prepareQuery(queryObject); if (values != null) { @@ -1015,8 +1003,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe if (paramNames != null && values != null && paramNames.length != values.length) { throw new IllegalArgumentException("Length of paramNames array must match length of values array"); } - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.getNamedQuery(queryName); prepareQuery(queryObject); if (values != null) { @@ -1032,8 +1020,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe public List findByNamedQueryAndValueBean(final String queryName, final Object valueBean) throws DataAccessException { - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Query queryObject = session.getNamedQuery(queryName); prepareQuery(queryObject); queryObject.setProperties(valueBean); @@ -1055,8 +1043,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe throws DataAccessException { Assert.notNull(criteria, "DetachedCriteria must not be null"); - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Criteria executableCriteria = criteria.getExecutableCriteria(session); prepareCriteria(executableCriteria); if (firstResult >= 0) { @@ -1087,8 +1075,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe throws DataAccessException { Assert.notNull(exampleEntity, "Example entity must not be null"); - return (List) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public List doInHibernate(Session session) throws HibernateException { Criteria executableCriteria = (entityName != null ? session.createCriteria(entityName) : session.createCriteria(exampleEntity.getClass())); executableCriteria.add(Example.create(exampleEntity)); @@ -1118,8 +1106,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public Iterator iterate(final String queryString, final Object... values) throws DataAccessException { - return (Iterator) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public Iterator doInHibernate(Session session) throws HibernateException { Query queryObject = session.createQuery(queryString); prepareQuery(queryObject); if (values != null) { @@ -1150,8 +1138,8 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe } public int bulkUpdate(final String queryString, final Object... values) throws DataAccessException { - return (Integer) executeWithNativeSession(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { + return executeWithNativeSession(new HibernateCallback() { + public Integer doInHibernate(Session session) throws HibernateException { Query queryObject = session.createQuery(queryString); prepareQuery(queryObject); if (values != null) { diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java index 57c21c42d745c917ea7cdbfa02db7282655d5fda..d9005b4101dc664873099eb86d25a0ada05fccb2 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java @@ -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; diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java index b36df9a455a0aa26090bfde8da77c588f447a5b5..c910ae09d5ee748c7d0f99bb3f7b672486fbabbd 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.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. @@ -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); } /** diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/ibatis/SqlMapClientFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/ibatis/SqlMapClientFactoryBean.java index 603e908b3451043232174020b2b1c3a4739d942d..b3b9e706a79cc0d27c5bb2faf7c7c9116d07a896 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/ibatis/SqlMapClientFactoryBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/ibatis/SqlMapClientFactoryBean.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.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, 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 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 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 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 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 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 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 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 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 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 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 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 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() {