Drop JDO support
Issue: SPR-14130
This commit is contained in:
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import javax.jdo.Constants;
|
||||
import javax.jdo.JDOException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.Transaction;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.jdbc.datasource.ConnectionHandle;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link JdoDialect} interface.
|
||||
* As of Spring 4.0, designed for JDO 3.0 (or rather, semantics beyond JDO 3.0).
|
||||
* Used as default dialect by {@link JdoTransactionManager}.
|
||||
*
|
||||
* <p>Simply begins a standard JDO transaction in {@code beginTransaction}.
|
||||
* Returns a handle for a JDO DataStoreConnection on {@code getJdbcConnection}.
|
||||
* Calls the corresponding JDO PersistenceManager operation on {@code flush}
|
||||
* Uses a Spring SQLExceptionTranslator for exception translation, if applicable.
|
||||
*
|
||||
* <p>Note that, even with JDO 3.0, vendor-specific subclasses are still necessary
|
||||
* for special transaction semantics and more sophisticated exception translation.
|
||||
* Furthermore, vendor-specific subclasses are encouraged to expose the native JDBC
|
||||
* Connection on {@code getJdbcConnection}, rather than JDO 3.0's wrapper handle.
|
||||
*
|
||||
* <p>This class also implements the PersistenceExceptionTranslator interface,
|
||||
* as autodetected by Spring's PersistenceExceptionTranslationPostProcessor,
|
||||
* for AOP-based translation of native exceptions to Spring DataAccessExceptions.
|
||||
* Hence, the presence of a standard DefaultJdoDialect bean automatically enables
|
||||
* a PersistenceExceptionTranslationPostProcessor to translate JDO exceptions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see #setJdbcExceptionTranslator
|
||||
* @see JdoTransactionManager#setJdoDialect
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
*/
|
||||
public class DefaultJdoDialect implements JdoDialect, PersistenceExceptionTranslator {
|
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DefaultJdoDialect.
|
||||
*/
|
||||
public DefaultJdoDialect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DefaultJdoDialect.
|
||||
* @param connectionFactory the connection factory of the JDO PersistenceManagerFactory,
|
||||
* which is used to initialize the default JDBC exception translator
|
||||
* @see javax.jdo.PersistenceManagerFactory#getConnectionFactory()
|
||||
* @see PersistenceManagerFactoryUtils#newJdbcExceptionTranslator(Object)
|
||||
*/
|
||||
public DefaultJdoDialect(Object connectionFactory) {
|
||||
this.jdbcExceptionTranslator = PersistenceManagerFactoryUtils.newJdbcExceptionTranslator(connectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC exception translator for this dialect.
|
||||
* <p>Applied to any SQLException root cause of a JDOException, if specified.
|
||||
* The default is to rely on the JDO provider's native exception translation.
|
||||
* @param jdbcExceptionTranslator exception translator
|
||||
* @see java.sql.SQLException
|
||||
* @see javax.jdo.JDOException#getCause()
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC exception translator for this dialect, if any.
|
||||
*/
|
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() {
|
||||
return this.jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Hooks for transaction management (used by JdoTransactionManager)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This implementation invokes the standard JDO {@link Transaction#begin()}
|
||||
* method and also {@link Transaction#setIsolationLevel(String)} if necessary.
|
||||
* @see javax.jdo.Transaction#begin
|
||||
* @see org.springframework.transaction.InvalidIsolationLevelException
|
||||
*/
|
||||
@Override
|
||||
public Object beginTransaction(Transaction transaction, TransactionDefinition definition)
|
||||
throws JDOException, SQLException, TransactionException {
|
||||
|
||||
String jdoIsolationLevel = getJdoIsolationLevel(definition);
|
||||
if (jdoIsolationLevel != null) {
|
||||
transaction.setIsolationLevel(jdoIsolationLevel);
|
||||
}
|
||||
transaction.begin();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the JDO isolation level String to use for the given
|
||||
* Spring transaction definition.
|
||||
* @param definition the Spring transaction definition
|
||||
* @return the corresponding JDO isolation level String, or {@code null}
|
||||
* to indicate that no isolation level should be set explicitly
|
||||
* @see Transaction#setIsolationLevel(String)
|
||||
* @see Constants#TX_SERIALIZABLE
|
||||
* @see Constants#TX_REPEATABLE_READ
|
||||
* @see Constants#TX_READ_COMMITTED
|
||||
* @see Constants#TX_READ_UNCOMMITTED
|
||||
*/
|
||||
protected String getJdoIsolationLevel(TransactionDefinition definition) {
|
||||
switch (definition.getIsolationLevel()) {
|
||||
case TransactionDefinition.ISOLATION_SERIALIZABLE:
|
||||
return Constants.TX_SERIALIZABLE;
|
||||
case TransactionDefinition.ISOLATION_REPEATABLE_READ:
|
||||
return Constants.TX_REPEATABLE_READ;
|
||||
case TransactionDefinition.ISOLATION_READ_COMMITTED:
|
||||
return Constants.TX_READ_COMMITTED;
|
||||
case TransactionDefinition.ISOLATION_READ_UNCOMMITTED:
|
||||
return Constants.TX_READ_UNCOMMITTED;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation does nothing, as the default beginTransaction implementation
|
||||
* does not require any cleanup.
|
||||
* @see #beginTransaction
|
||||
*/
|
||||
@Override
|
||||
public void cleanupTransaction(Object transactionData) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns a DataStoreConnectionHandle for JDO.
|
||||
* <p><b>NOTE:</b> A JDO DataStoreConnection is always a wrapper,
|
||||
* never the native JDBC Connection. If you need access to the native JDBC
|
||||
* Connection (or the connection pool handle, to be unwrapped via a Spring
|
||||
* NativeJdbcExtractor), override this method to return the native
|
||||
* Connection through the corresponding vendor-specific mechanism.
|
||||
* <p>A JDO DataStoreConnection is only "borrowed" from the PersistenceManager:
|
||||
* it needs to be returned as early as possible. Effectively, JDO requires the
|
||||
* fetched Connection to be closed before continuing PersistenceManager work.
|
||||
* For this reason, the exposed ConnectionHandle eagerly releases its JDBC
|
||||
* Connection at the end of each JDBC data access operation (that is, on
|
||||
* {@code DataSourceUtils.releaseConnection}).
|
||||
* @see javax.jdo.PersistenceManager#getDataStoreConnection()
|
||||
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
*/
|
||||
@Override
|
||||
public ConnectionHandle getJdbcConnection(PersistenceManager pm, boolean readOnly)
|
||||
throws JDOException, SQLException {
|
||||
|
||||
return new DataStoreConnectionHandle(pm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation does nothing, assuming that the Connection
|
||||
* will implicitly be closed with the PersistenceManager.
|
||||
* <p>If the JDO provider returns a Connection handle that it
|
||||
* expects the application to close, the dialect needs to invoke
|
||||
* {@code Connection.close} here.
|
||||
* @see java.sql.Connection#close()
|
||||
*/
|
||||
@Override
|
||||
public void releaseJdbcConnection(ConnectionHandle conHandle, PersistenceManager pm)
|
||||
throws JDOException, SQLException {
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Hook for exception translation (used by JdoTransactionManager)
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Implementation of the PersistenceExceptionTranslator interface,
|
||||
* as autodetected by Spring's PersistenceExceptionTranslationPostProcessor.
|
||||
* <p>Converts the exception if it is a JDOException, using this JdoDialect.
|
||||
* Else returns {@code null} to indicate an unknown exception.
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @see #translateException
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
if (ex instanceof JDOException) {
|
||||
return translateException((JDOException) ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to PersistenceManagerFactoryUtils.
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateException(JDOException ex) {
|
||||
if (getJdbcExceptionTranslator() != null && ex.getCause() instanceof SQLException) {
|
||||
return getJdbcExceptionTranslator().translate("JDO operation: " + ex.getMessage(),
|
||||
extractSqlStringFromException(ex), (SQLException) ex.getCause());
|
||||
}
|
||||
return PersistenceManagerFactoryUtils.convertJdoAccessException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for extracting a SQL String from the given exception.
|
||||
* <p>Default implementation always returns {@code null}. Can be overridden in
|
||||
* subclasses to extract SQL Strings for vendor-specific exception classes.
|
||||
* @param ex the JDOException, containing a SQLException
|
||||
* @return the SQL String, or {@code null} if none found
|
||||
*/
|
||||
protected String extractSqlStringFromException(JDOException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ConnectionHandle implementation that fetches a new JDO DataStoreConnection
|
||||
* for every {@code getConnection} call and closes the Connection on
|
||||
* {@code releaseConnection}. This is necessary because JDO requires the
|
||||
* fetched Connection to be closed before continuing PersistenceManager work.
|
||||
* @see javax.jdo.PersistenceManager#getDataStoreConnection()
|
||||
*/
|
||||
private static class DataStoreConnectionHandle implements ConnectionHandle {
|
||||
|
||||
private final PersistenceManager persistenceManager;
|
||||
|
||||
public DataStoreConnectionHandle(PersistenceManager persistenceManager) {
|
||||
this.persistenceManager = persistenceManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return (Connection) this.persistenceManager.getDataStoreConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseConnection(Connection con) {
|
||||
JdbcUtils.closeConnection(con);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.jdo.JDOException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.Transaction;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.datasource.ConnectionHandle;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
|
||||
/**
|
||||
* SPI strategy that allows for customizing integration with a specific JDO provider,
|
||||
* in particular regarding transaction management and exception translation. To be
|
||||
* implemented for specific JDO providers such as JPOX, Kodo, Lido, Versant Open Access.
|
||||
*
|
||||
* <p>JDO 3.0 defines standard ways for most of the functionality covered here.
|
||||
* Hence, Spring's {@link DefaultJdoDialect} uses the corresponding JDO 3.0 methods
|
||||
* by default, to be overridden in a vendor-specific fashion if necessary.
|
||||
* Vendor-specific subclasses of {@link DefaultJdoDialect} are still required for special
|
||||
* transaction semantics and more sophisticated exception translation (if needed).
|
||||
*
|
||||
* <p>In general, it is recommended to derive from {@link DefaultJdoDialect} instead
|
||||
* of implementing this interface directly. This allows for inheriting common
|
||||
* behavior (present and future) from {@link DefaultJdoDialect}, only overriding
|
||||
* specific hooks to plug in concrete vendor-specific behavior.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 02.11.2003
|
||||
* @see JdoTransactionManager#setJdoDialect
|
||||
* @see DefaultJdoDialect
|
||||
*/
|
||||
public interface JdoDialect {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Hooks for transaction management (used by JdoTransactionManager)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Begin the given JDO transaction, applying the semantics specified by the
|
||||
* given Spring transaction definition (in particular, an isolation level
|
||||
* and a timeout). Invoked by JdoTransactionManager on transaction begin.
|
||||
* <p>An implementation can configure the JDO Transaction object and then
|
||||
* invoke {@code begin}, or invoke a special begin method that takes,
|
||||
* for example, an isolation level.
|
||||
* <p>An implementation can also apply read-only flag and isolation level to the
|
||||
* underlying JDBC Connection before beginning the transaction. In that case,
|
||||
* a transaction data object can be returned that holds the previous isolation
|
||||
* level (and possibly other data), to be reset in {@code cleanupTransaction}.
|
||||
* <p>Implementations can also use the Spring transaction name, as exposed by the
|
||||
* passed-in TransactionDefinition, to optimize for specific data access use cases
|
||||
* (effectively using the current transaction name as use case identifier).
|
||||
* @param transaction the JDO transaction to begin
|
||||
* @param definition the Spring transaction definition that defines semantics
|
||||
* @return an arbitrary object that holds transaction data, if any
|
||||
* (to be passed into cleanupTransaction)
|
||||
* @throws JDOException if thrown by JDO methods
|
||||
* @throws SQLException if thrown by JDBC methods
|
||||
* @throws TransactionException in case of invalid arguments
|
||||
* @see #cleanupTransaction
|
||||
* @see javax.jdo.Transaction#begin
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction
|
||||
*/
|
||||
Object beginTransaction(Transaction transaction, TransactionDefinition definition)
|
||||
throws JDOException, SQLException, TransactionException;
|
||||
|
||||
/**
|
||||
* Clean up the transaction via the given transaction data.
|
||||
* Invoked by JdoTransactionManager on transaction cleanup.
|
||||
* <p>An implementation can, for example, reset read-only flag and
|
||||
* isolation level of the underlying JDBC Connection. Furthermore,
|
||||
* an exposed data access use case can be reset here.
|
||||
* @param transactionData arbitrary object that holds transaction data, if any
|
||||
* (as returned by beginTransaction)
|
||||
* @see #beginTransaction
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#resetConnectionAfterTransaction
|
||||
*/
|
||||
void cleanupTransaction(Object transactionData);
|
||||
|
||||
/**
|
||||
* Retrieve the JDBC Connection that the given JDO PersistenceManager uses underneath,
|
||||
* if accessing a relational database. This method will just get invoked if actually
|
||||
* needing access to the underlying JDBC Connection, usually within an active JDO
|
||||
* transaction (for example, by JdoTransactionManager). The returned handle will
|
||||
* be passed into the {@code releaseJdbcConnection} method when not needed anymore.
|
||||
* <p>Implementations are encouraged to return an unwrapped Connection object, i.e.
|
||||
* the Connection as they got it from the connection pool. This makes it easier for
|
||||
* application code to get at the underlying native JDBC Connection, like an
|
||||
* OracleConnection, which is sometimes necessary for LOB handling etc. We assume
|
||||
* that calling code knows how to properly handle the returned Connection object.
|
||||
* <p>In a simple case where the returned Connection will be auto-closed with the
|
||||
* PersistenceManager or can be released via the Connection object itself, an
|
||||
* implementation can return a SimpleConnectionHandle that just contains the
|
||||
* Connection. If some other object is needed in {@code releaseJdbcConnection},
|
||||
* an implementation should use a special handle that references that other object.
|
||||
* @param pm the current JDO PersistenceManager
|
||||
* @param readOnly whether the Connection is only needed for read-only purposes
|
||||
* @return a handle for the JDBC Connection, to be passed into
|
||||
* {@code releaseJdbcConnection}, or {@code null}
|
||||
* if no JDBC Connection can be retrieved
|
||||
* @throws JDOException if thrown by JDO methods
|
||||
* @throws SQLException if thrown by JDBC methods
|
||||
* @see #releaseJdbcConnection
|
||||
* @see org.springframework.jdbc.datasource.ConnectionHandle#getConnection
|
||||
* @see org.springframework.jdbc.datasource.SimpleConnectionHandle
|
||||
* @see JdoTransactionManager#setDataSource
|
||||
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
|
||||
*/
|
||||
ConnectionHandle getJdbcConnection(PersistenceManager pm, boolean readOnly)
|
||||
throws JDOException, SQLException;
|
||||
|
||||
/**
|
||||
* Release the given JDBC Connection, which has originally been retrieved
|
||||
* via {@code getJdbcConnection}. This should be invoked in any case,
|
||||
* to allow for proper release of the retrieved Connection handle.
|
||||
* <p>An implementation might simply do nothing, if the Connection returned
|
||||
* by {@code getJdbcConnection} will be implicitly closed when the JDO
|
||||
* transaction completes or when the PersistenceManager is closed.
|
||||
* @param conHandle the JDBC Connection handle to release
|
||||
* @param pm the current JDO PersistenceManager
|
||||
* @throws JDOException if thrown by JDO methods
|
||||
* @throws SQLException if thrown by JDBC methods
|
||||
* @see #getJdbcConnection
|
||||
*/
|
||||
void releaseJdbcConnection(ConnectionHandle conHandle, PersistenceManager pm)
|
||||
throws JDOException, SQLException;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Hook for exception translation (used by JdoTransactionManager)
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Translate the given JDOException to a corresponding exception from Spring's
|
||||
* generic DataAccessException hierarchy. An implementation should apply
|
||||
* PersistenceManagerFactoryUtils' standard exception translation if can't do
|
||||
* anything more specific.
|
||||
* <p>Of particular importance is the correct translation to
|
||||
* DataIntegrityViolationException, for example on constraint violation.
|
||||
* Unfortunately, standard JDO does not allow for portable detection of this.
|
||||
* <p>Can use a SQLExceptionTranslator for translating underlying SQLExceptions
|
||||
* in a database-specific fashion.
|
||||
* @param ex the JDOException thrown
|
||||
* @return the corresponding DataAccessException (must not be {@code null})
|
||||
* @see JdoTransactionManager#convertJdoAccessException
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
* @see org.springframework.dao.DataIntegrityViolationException
|
||||
* @see org.springframework.jdbc.support.SQLExceptionTranslator
|
||||
*/
|
||||
DataAccessException translateException(JDOException ex);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDOHelper;
|
||||
import javax.jdo.JDOObjectNotFoundException;
|
||||
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* JDO-specific subclass of ObjectRetrievalFailureException.
|
||||
* Converts JDO's JDOObjectNotFoundException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoObjectRetrievalFailureException extends ObjectRetrievalFailureException {
|
||||
|
||||
public JdoObjectRetrievalFailureException(JDOObjectNotFoundException ex) {
|
||||
// Extract information about the failed object from the JDOException, if available.
|
||||
super((ex.getFailedObject() != null ? ex.getFailedObject().getClass() : null),
|
||||
(ex.getFailedObject() != null ? JDOHelper.getObjectId(ex.getFailedObject()) : null),
|
||||
ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDOHelper;
|
||||
import javax.jdo.JDOOptimisticVerificationException;
|
||||
|
||||
import org.springframework.orm.ObjectOptimisticLockingFailureException;
|
||||
|
||||
/**
|
||||
* JDO-specific subclass of ObjectOptimisticLockingFailureException.
|
||||
* Converts JDO's JDOOptimisticVerificationException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
|
||||
|
||||
public JdoOptimisticLockingFailureException(JDOOptimisticVerificationException ex) {
|
||||
// Extract information about the failed object from the JDOException, if available.
|
||||
super((ex.getFailedObject() != null ? ex.getFailedObject().getClass() : null),
|
||||
(ex.getFailedObject() != null ? JDOHelper.getObjectId(ex.getFailedObject()) : null),
|
||||
ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDODataStoreException;
|
||||
import javax.jdo.JDOFatalDataStoreException;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* JDO-specific subclass of DataAccessResourceFailureException.
|
||||
* Converts JDO's JDODataStoreException and JDOFatalDataStoreException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoResourceFailureException extends DataAccessResourceFailureException {
|
||||
|
||||
public JdoResourceFailureException(JDODataStoreException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public JdoResourceFailureException(JDOFatalDataStoreException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDOException;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* JDO-specific subclass of UncategorizedDataAccessException,
|
||||
* for JDO system errors that do not match any concrete
|
||||
* {@code org.springframework.dao} exceptions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
public JdoSystemException(JDOException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,619 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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;
|
||||
|
||||
import javax.jdo.JDOException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
import javax.jdo.Transaction;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.datasource.ConnectionHandle;
|
||||
import org.springframework.jdbc.datasource.ConnectionHolder;
|
||||
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
|
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.DelegatingTransactionDefinition;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation for a
|
||||
* single JDO {@link javax.jdo.PersistenceManagerFactory}. Binds a JDO PersistenceManager
|
||||
* from the specified factory to the thread, potentially allowing for one thread-bound
|
||||
* PersistenceManager per factory. {@link PersistenceManagerFactoryUtils} and
|
||||
* {@link org.springframework.orm.jdo.support.SpringPersistenceManagerProxyBean} are aware
|
||||
* of thread-bound persistence managers and participate in such transactions automatically.
|
||||
* Using either of those (or going through a {@link TransactionAwarePersistenceManagerFactoryProxy}
|
||||
* is required for JDO access code supporting this transaction management mechanism.
|
||||
*
|
||||
* <p>This transaction manager is appropriate for applications that use a single
|
||||
* JDO PersistenceManagerFactory for transactional data access. JTA (usually through
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager}) is necessary
|
||||
* for accessing multiple transactional resources within the same transaction.
|
||||
* Note that you need to configure your JDO provider accordingly in order to make
|
||||
* it participate in JTA transactions.
|
||||
*
|
||||
* <p>This transaction manager also supports direct DataSource access within a
|
||||
* transaction (i.e. plain JDBC code working with the same DataSource).
|
||||
* This allows for mixing services which access JDO and services which use plain
|
||||
* JDBC (without being aware of JDO)! Application code needs to stick to the
|
||||
* same simple Connection lookup pattern as with
|
||||
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
|
||||
* (i.e. {@link org.springframework.jdbc.datasource.DataSourceUtils#getConnection}
|
||||
* or going through a
|
||||
* {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy}).
|
||||
*
|
||||
* <p>Note: To be able to register a DataSource's Connection for plain JDBC code,
|
||||
* this instance needs to be aware of the DataSource ({@link #setDataSource}).
|
||||
* The given DataSource should obviously match the one used by the given
|
||||
* PersistenceManagerFactory. This transaction manager will autodetect the DataSource
|
||||
* that acts as "connectionFactory" of the PersistenceManagerFactory, so you usually
|
||||
* don't need to explicitly specify the "dataSource" property.
|
||||
*
|
||||
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
|
||||
* The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults
|
||||
* to "false", though, as nested transactions will just apply to the JDBC Connection,
|
||||
* not to the JDO PersistenceManager and its cached entity objects and related context.
|
||||
* You can manually set the flag to "true" if you want to use nested transactions
|
||||
* for JDBC access code which participates in JDO transactions (provided that your
|
||||
* JDBC driver supports Savepoints). <i>Note that JDO itself does not support
|
||||
* nested transactions! Hence, do not expect JDO access code to semantically
|
||||
* participate in a nested transaction.</i>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see #setPersistenceManagerFactory
|
||||
* @see #setDataSource
|
||||
* @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
|
||||
* @see LocalPersistenceManagerFactoryBean
|
||||
* @see PersistenceManagerFactoryUtils#getPersistenceManager
|
||||
* @see PersistenceManagerFactoryUtils#releasePersistenceManager
|
||||
* @see TransactionAwarePersistenceManagerFactoryProxy
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, InitializingBean {
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private boolean autodetectDataSource = true;
|
||||
|
||||
private JdoDialect jdoDialect;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new JdoTransactionManager instance.
|
||||
* A PersistenceManagerFactory has to be set to be able to use it.
|
||||
* @see #setPersistenceManagerFactory
|
||||
*/
|
||||
public JdoTransactionManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JdoTransactionManager instance.
|
||||
* @param pmf PersistenceManagerFactory to manage transactions for
|
||||
*/
|
||||
public JdoTransactionManager(PersistenceManagerFactory pmf) {
|
||||
this.persistenceManagerFactory = pmf;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the PersistenceManagerFactory that this instance should manage transactions for.
|
||||
* <p>The PersistenceManagerFactory specified here should be the target
|
||||
* PersistenceManagerFactory to manage transactions for, not a
|
||||
* TransactionAwarePersistenceManagerFactoryProxy. Only data access
|
||||
* code may work with TransactionAwarePersistenceManagerFactoryProxy, while the
|
||||
* transaction manager needs to work on the underlying target PersistenceManagerFactory.
|
||||
* @see TransactionAwarePersistenceManagerFactoryProxy
|
||||
*/
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
|
||||
this.persistenceManagerFactory = pmf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistenceManagerFactory that this instance should manage transactions for.
|
||||
*/
|
||||
public PersistenceManagerFactory getPersistenceManagerFactory() {
|
||||
return this.persistenceManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC DataSource that this instance should manage transactions for.
|
||||
* The DataSource should match the one used by the JDO PersistenceManagerFactory:
|
||||
* for example, you could specify the same JNDI DataSource for both.
|
||||
* <p>If the PersistenceManagerFactory uses a DataSource as connection factory,
|
||||
* the DataSource will be autodetected: You can still explicitly specify the
|
||||
* DataSource, but you don't need to in this case.
|
||||
* <p>A transactional JDBC Connection for this DataSource will be provided to
|
||||
* application code accessing this DataSource directly via DataSourceUtils
|
||||
* or JdbcTemplate. The Connection will be taken from the JDO PersistenceManager.
|
||||
* <p>Note that you need to use a JDO dialect for a specific JDO provider to
|
||||
* allow for exposing JDO transactions as JDBC transactions.
|
||||
* <p>The DataSource specified here should be the target DataSource to manage
|
||||
* transactions for, not a TransactionAwareDataSourceProxy. Only data access
|
||||
* code may work with TransactionAwareDataSourceProxy, while the transaction
|
||||
* manager needs to work on the underlying target DataSource. If there's
|
||||
* nevertheless a TransactionAwareDataSourceProxy passed in, it will be
|
||||
* unwrapped to extract its target DataSource.
|
||||
* @see #setAutodetectDataSource
|
||||
* @see #setJdoDialect
|
||||
* @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
|
||||
* @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
if (dataSource instanceof TransactionAwareDataSourceProxy) {
|
||||
// If we got a TransactionAwareDataSourceProxy, we need to perform transactions
|
||||
// for its underlying target DataSource, else data access code won't see
|
||||
// properly exposed transactions (i.e. transactions for the target DataSource).
|
||||
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
|
||||
}
|
||||
else {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC DataSource that this instance manages transactions for.
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to autodetect a JDBC DataSource used by the JDO PersistenceManagerFactory,
|
||||
* as returned by the {@code getConnectionFactory()} method. Default is "true".
|
||||
* <p>Can be turned off to deliberately ignore an available DataSource,
|
||||
* to not expose JDO transactions as JDBC transactions for that DataSource.
|
||||
* @see #setDataSource
|
||||
* @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
|
||||
*/
|
||||
public void setAutodetectDataSource(boolean autodetectDataSource) {
|
||||
this.autodetectDataSource = autodetectDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDO dialect to use for this transaction manager.
|
||||
* <p>The dialect object can be used to retrieve the underlying JDBC connection
|
||||
* and thus allows for exposing JDO transactions as JDBC transactions.
|
||||
* @see JdoDialect#getJdbcConnection
|
||||
*/
|
||||
public void setJdoDialect(JdoDialect jdoDialect) {
|
||||
this.jdoDialect = jdoDialect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDO dialect to use for this transaction manager.
|
||||
* <p>Creates a default one for the specified PersistenceManagerFactory if none set.
|
||||
*/
|
||||
public JdoDialect getJdoDialect() {
|
||||
if (this.jdoDialect == null) {
|
||||
this.jdoDialect = new DefaultJdoDialect();
|
||||
}
|
||||
return this.jdoDialect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly initialize the JDO dialect, creating a default one
|
||||
* for the specified PersistenceManagerFactory if none set.
|
||||
* Auto-detect the PersistenceManagerFactory's DataSource, if any.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getPersistenceManagerFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'persistenceManagerFactory' is required");
|
||||
}
|
||||
// Build default JdoDialect if none explicitly specified.
|
||||
if (this.jdoDialect == null) {
|
||||
this.jdoDialect = new DefaultJdoDialect(getPersistenceManagerFactory().getConnectionFactory());
|
||||
}
|
||||
|
||||
// Check for DataSource as connection factory.
|
||||
if (this.autodetectDataSource && getDataSource() == null) {
|
||||
Object pmfcf = getPersistenceManagerFactory().getConnectionFactory();
|
||||
if (pmfcf instanceof DataSource) {
|
||||
// Use the PersistenceManagerFactory's DataSource for exposing transactions to JDBC code.
|
||||
this.dataSource = (DataSource) pmfcf;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Using DataSource [" + this.dataSource +
|
||||
"] of JDO PersistenceManagerFactory for JdoTransactionManager");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getPersistenceManagerFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
JdoTransactionObject txObject = new JdoTransactionObject();
|
||||
txObject.setSavepointAllowed(isNestedTransactionAllowed());
|
||||
|
||||
PersistenceManagerHolder pmHolder = (PersistenceManagerHolder)
|
||||
TransactionSynchronizationManager.getResource(getPersistenceManagerFactory());
|
||||
if (pmHolder != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found thread-bound PersistenceManager [" +
|
||||
pmHolder.getPersistenceManager() + "] for JDO transaction");
|
||||
}
|
||||
txObject.setPersistenceManagerHolder(pmHolder, false);
|
||||
}
|
||||
|
||||
if (getDataSource() != null) {
|
||||
ConnectionHolder conHolder = (ConnectionHolder)
|
||||
TransactionSynchronizationManager.getResource(getDataSource());
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
|
||||
return txObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return ((JdoTransactionObject) transaction).hasTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) transaction;
|
||||
|
||||
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Pre-bound JDBC Connection found! JdoTransactionManager does not support " +
|
||||
"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
|
||||
"It is recommended to use a single JdoTransactionManager for all transactions " +
|
||||
"on a single DataSource, no matter whether JDO or JDBC access.");
|
||||
}
|
||||
|
||||
PersistenceManager pm;
|
||||
|
||||
try {
|
||||
if (txObject.getPersistenceManagerHolder() == null ||
|
||||
txObject.getPersistenceManagerHolder().isSynchronizedWithTransaction()) {
|
||||
PersistenceManager newPm = getPersistenceManagerFactory().getPersistenceManager();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened new PersistenceManager [" + newPm + "] for JDO transaction");
|
||||
}
|
||||
txObject.setPersistenceManagerHolder(new PersistenceManagerHolder(newPm), true);
|
||||
}
|
||||
|
||||
pm = txObject.getPersistenceManagerHolder().getPersistenceManager();
|
||||
|
||||
// Delegate to JdoDialect for actual transaction begin.
|
||||
final int timeoutToUse = determineTimeout(definition);
|
||||
Object transactionData = getJdoDialect().beginTransaction(pm.currentTransaction(),
|
||||
new DelegatingTransactionDefinition(definition) {
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return timeoutToUse;
|
||||
}
|
||||
});
|
||||
txObject.setTransactionData(transactionData);
|
||||
|
||||
// Register transaction timeout.
|
||||
if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
txObject.getPersistenceManagerHolder().setTimeoutInSeconds(timeoutToUse);
|
||||
}
|
||||
|
||||
// Register the JDO PersistenceManager's JDBC Connection for the DataSource, if set.
|
||||
if (getDataSource() != null) {
|
||||
ConnectionHandle conHandle = getJdoDialect().getJdbcConnection(pm, definition.isReadOnly());
|
||||
if (conHandle != null) {
|
||||
ConnectionHolder conHolder = new ConnectionHolder(conHandle);
|
||||
if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
conHolder.setTimeoutInSeconds(timeoutToUse);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exposing JDO transaction as JDBC transaction [" +
|
||||
conHolder.getConnectionHandle() + "]");
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not exposing JDO transaction [" + pm + "] as JDBC transaction because " +
|
||||
"JdoDialect [" + getJdoDialect() + "] does not support JDBC Connection retrieval");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bind the persistence manager holder to the thread.
|
||||
if (txObject.isNewPersistenceManagerHolder()) {
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getPersistenceManagerFactory(), txObject.getPersistenceManagerHolder());
|
||||
}
|
||||
txObject.getPersistenceManagerHolder().setSynchronizedWithTransaction(true);
|
||||
}
|
||||
|
||||
catch (TransactionException ex) {
|
||||
closePersistenceManagerAfterFailedBegin(txObject);
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
closePersistenceManagerAfterFailedBegin(txObject);
|
||||
throw new CannotCreateTransactionException("Could not open JDO PersistenceManager for transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current transaction's EntityManager.
|
||||
* Called after a transaction begin attempt failed.
|
||||
* @param txObject the current transaction
|
||||
*/
|
||||
protected void closePersistenceManagerAfterFailedBegin(JdoTransactionObject txObject) {
|
||||
if (txObject.isNewPersistenceManagerHolder()) {
|
||||
PersistenceManager pm = txObject.getPersistenceManagerHolder().getPersistenceManager();
|
||||
try {
|
||||
if (pm.currentTransaction().isActive()) {
|
||||
pm.currentTransaction().rollback();
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Could not rollback PersistenceManager after failed transaction begin", ex);
|
||||
}
|
||||
finally {
|
||||
PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
|
||||
}
|
||||
txObject.setPersistenceManagerHolder(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doSuspend(Object transaction) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) transaction;
|
||||
txObject.setPersistenceManagerHolder(null, false);
|
||||
PersistenceManagerHolder persistenceManagerHolder = (PersistenceManagerHolder)
|
||||
TransactionSynchronizationManager.unbindResource(getPersistenceManagerFactory());
|
||||
txObject.setConnectionHolder(null);
|
||||
ConnectionHolder connectionHolder = null;
|
||||
if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getDataSource())) {
|
||||
connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
}
|
||||
return new SuspendedResourcesHolder(persistenceManagerHolder, connectionHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) {
|
||||
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getPersistenceManagerFactory(), resourcesHolder.getPersistenceManagerHolder());
|
||||
if (getDataSource() != null && resourcesHolder.getConnectionHolder() != null) {
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns "true": a JDO commit will properly handle
|
||||
* transactions that have been marked rollback-only at a global level.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldCommitOnGlobalRollbackOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing JDO transaction on PersistenceManager [" +
|
||||
txObject.getPersistenceManagerHolder().getPersistenceManager() + "]");
|
||||
}
|
||||
try {
|
||||
Transaction tx = txObject.getPersistenceManagerHolder().getPersistenceManager().currentTransaction();
|
||||
tx.commit();
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
// Assumably failed to flush changes to database.
|
||||
throw convertJdoAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back JDO transaction on PersistenceManager [" +
|
||||
txObject.getPersistenceManagerHolder().getPersistenceManager() + "]");
|
||||
}
|
||||
try {
|
||||
Transaction tx = txObject.getPersistenceManagerHolder().getPersistenceManager().currentTransaction();
|
||||
if (tx.isActive()) {
|
||||
tx.rollback();
|
||||
}
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw new TransactionSystemException("Could not roll back JDO transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting JDO transaction on PersistenceManager [" +
|
||||
txObject.getPersistenceManagerHolder().getPersistenceManager() + "] rollback-only");
|
||||
}
|
||||
txObject.setRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
JdoTransactionObject txObject = (JdoTransactionObject) transaction;
|
||||
|
||||
// Remove the persistence manager holder from the thread.
|
||||
if (txObject.isNewPersistenceManagerHolder()) {
|
||||
TransactionSynchronizationManager.unbindResource(getPersistenceManagerFactory());
|
||||
}
|
||||
txObject.getPersistenceManagerHolder().clear();
|
||||
|
||||
// Remove the JDBC connection holder from the thread, if exposed.
|
||||
if (txObject.hasConnectionHolder()) {
|
||||
TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
try {
|
||||
getJdoDialect().releaseJdbcConnection(txObject.getConnectionHolder().getConnectionHandle(),
|
||||
txObject.getPersistenceManagerHolder().getPersistenceManager());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Just log it, to keep a transaction-related exception.
|
||||
logger.debug("Could not release JDBC connection after transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
getJdoDialect().cleanupTransaction(txObject.getTransactionData());
|
||||
|
||||
if (txObject.isNewPersistenceManagerHolder()) {
|
||||
PersistenceManager pm = txObject.getPersistenceManagerHolder().getPersistenceManager();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing JDO PersistenceManager [" + pm + "] after transaction");
|
||||
}
|
||||
PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
|
||||
}
|
||||
else {
|
||||
logger.debug("Not closing pre-bound JDO PersistenceManager after transaction");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given JDOException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy.
|
||||
* <p>The default implementation delegates to the JdoDialect.
|
||||
* May be overridden in subclasses.
|
||||
* @param ex JDOException that occured
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see JdoDialect#translateException
|
||||
*/
|
||||
protected DataAccessException convertJdoAccessException(JDOException ex) {
|
||||
return getJdoDialect().translateException(ex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JDO transaction object, representing a PersistenceManagerHolder.
|
||||
* Used as transaction object by JdoTransactionManager.
|
||||
*/
|
||||
private class JdoTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private PersistenceManagerHolder persistenceManagerHolder;
|
||||
|
||||
private boolean newPersistenceManagerHolder;
|
||||
|
||||
private Object transactionData;
|
||||
|
||||
public void setPersistenceManagerHolder(
|
||||
PersistenceManagerHolder persistenceManagerHolder, boolean newPersistenceManagerHolder) {
|
||||
this.persistenceManagerHolder = persistenceManagerHolder;
|
||||
this.newPersistenceManagerHolder = newPersistenceManagerHolder;
|
||||
}
|
||||
|
||||
public PersistenceManagerHolder getPersistenceManagerHolder() {
|
||||
return this.persistenceManagerHolder;
|
||||
}
|
||||
|
||||
public boolean isNewPersistenceManagerHolder() {
|
||||
return this.newPersistenceManagerHolder;
|
||||
}
|
||||
|
||||
public boolean hasTransaction() {
|
||||
return (this.persistenceManagerHolder != null && this.persistenceManagerHolder.isTransactionActive());
|
||||
}
|
||||
|
||||
public void setTransactionData(Object transactionData) {
|
||||
this.transactionData = transactionData;
|
||||
this.persistenceManagerHolder.setTransactionActive(true);
|
||||
}
|
||||
|
||||
public Object getTransactionData() {
|
||||
return this.transactionData;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
Transaction tx = this.persistenceManagerHolder.getPersistenceManager().currentTransaction();
|
||||
if (tx.isActive()) {
|
||||
tx.setRollbackOnly();
|
||||
}
|
||||
if (hasConnectionHolder()) {
|
||||
getConnectionHolder().setRollbackOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
Transaction tx = this.persistenceManagerHolder.getPersistenceManager().currentTransaction();
|
||||
return tx.getRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
this.persistenceManagerHolder.getPersistenceManager().flush();
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw convertJdoAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holder for suspended resources.
|
||||
* Used internally by {@code doSuspend} and {@code doResume}.
|
||||
*/
|
||||
private static class SuspendedResourcesHolder {
|
||||
|
||||
private final PersistenceManagerHolder persistenceManagerHolder;
|
||||
|
||||
private final ConnectionHolder connectionHolder;
|
||||
|
||||
private SuspendedResourcesHolder(PersistenceManagerHolder pmHolder, ConnectionHolder conHolder) {
|
||||
this.persistenceManagerHolder = pmHolder;
|
||||
this.connectionHolder = conHolder;
|
||||
}
|
||||
|
||||
private PersistenceManagerHolder getPersistenceManagerHolder() {
|
||||
return this.persistenceManagerHolder;
|
||||
}
|
||||
|
||||
private ConnectionHolder getConnectionHolder() {
|
||||
return this.connectionHolder;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDOFatalUserException;
|
||||
import javax.jdo.JDOUserException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* JDO-specific subclass of InvalidDataAccessApiUsageException.
|
||||
* Converts JDO's JDOUserException and JDOFatalUserException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JdoUsageException extends InvalidDataAccessApiUsageException {
|
||||
|
||||
public JdoUsageException(JDOUserException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public JdoUsageException(JDOFatalUserException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
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;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} that creates a
|
||||
* JDO {@link javax.jdo.PersistenceManagerFactory}. This is the usual way to
|
||||
* set up a shared JDO PersistenceManagerFactory in a Spring application context;
|
||||
* the PersistenceManagerFactory can then be passed to JDO-based DAOs via
|
||||
* dependency injection. Note that switching to a JNDI lookup or to a bean-style
|
||||
* PersistenceManagerFactory instance is just a matter of configuration!
|
||||
*
|
||||
* <p><b>NOTE: This class requires JDO 3.0 or higher, as of Spring 4.0.</b>
|
||||
* It will also expose the JPA {@link javax.persistence.EntityManagerFactory} as long
|
||||
* as the JDO provider creates a {@link javax.jdo.JDOEntityManagerFactory} reference
|
||||
* underneath, which means that this class can be used as a replacement for
|
||||
* {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean} in such a scenario.
|
||||
*
|
||||
* <p>Configuration settings can either be read from a properties file,
|
||||
* specified as "configLocation", or locally specified. Properties
|
||||
* specified as "jdoProperties" here will override any settings in a file.
|
||||
* You may alternatively specify a "persistenceManagerFactoryName",
|
||||
* referring to a PMF definition in "META-INF/jdoconfig.xml"
|
||||
* (see {@link #setPersistenceManagerFactoryName}).
|
||||
*
|
||||
* <p>This class also implements the
|
||||
* {@link org.springframework.dao.support.PersistenceExceptionTranslator}
|
||||
* interface, as autodetected by Spring's
|
||||
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
|
||||
* for AOP-based translation of native exceptions to Spring DataAccessExceptions.
|
||||
* Hence, the presence of a LocalPersistenceManagerFactoryBean automatically enables
|
||||
* a PersistenceExceptionTranslationPostProcessor to translate JDO exceptions.
|
||||
*
|
||||
* <p><b>Alternative: Configuration of a PersistenceManagerFactory provider bean</b>
|
||||
*
|
||||
* <p>As alternative to the properties-driven approach that this FactoryBean offers
|
||||
* (which is analogous to using the standard JDOHelper class with a Properties
|
||||
* object that is populated with standard JDO properties), you can set up an
|
||||
* instance of your PersistenceManagerFactory implementation class directly.
|
||||
*
|
||||
* <p>Like a DataSource, a PersistenceManagerFactory is encouraged to
|
||||
* support bean-style configuration, which makes it very easy to set up as
|
||||
* Spring-managed bean. The implementation class becomes the bean class;
|
||||
* the remaining properties are applied as bean properties (starting with
|
||||
* lower-case characters, in contrast to the corresponding JDO properties).
|
||||
*
|
||||
* <p>For example, in case of <a href="http://www.jpox.org">JPOX</a>:
|
||||
*
|
||||
* <p><pre class="code">
|
||||
* <bean id="persistenceManagerFactory" class="org.jpox.PersistenceManagerFactoryImpl" destroy-method="close">
|
||||
* <property name="connectionFactory" ref="dataSource"/>
|
||||
* <property name="nontransactionalRead" value="true"/>
|
||||
* </bean>
|
||||
* </pre>
|
||||
*
|
||||
* <p>Note that such direct setup of a PersistenceManagerFactory implementation
|
||||
* is the only way to pass an external connection factory (i.e. a JDBC DataSource)
|
||||
* into a JDO PersistenceManagerFactory. With the standard properties-driven approach,
|
||||
* you can only use an internal connection pool or a JNDI DataSource.
|
||||
*
|
||||
* <p>The {@code close()} method is standardized in JDO; don't forget to
|
||||
* specify it as "destroy-method" for any PersistenceManagerFactory instance.
|
||||
* Note that this FactoryBean will automatically invoke {@code close()} for
|
||||
* the PersistenceManagerFactory that it creates, without any special configuration.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see JdoTransactionManager#setPersistenceManagerFactory
|
||||
* @see org.springframework.jndi.JndiObjectFactoryBean
|
||||
* @see javax.jdo.JDOHelper#getPersistenceManagerFactory
|
||||
* @see javax.jdo.PersistenceManagerFactory#setConnectionFactory
|
||||
* @see javax.jdo.PersistenceManagerFactory#close()
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
*/
|
||||
public class LocalPersistenceManagerFactoryBean implements FactoryBean<PersistenceManagerFactory>,
|
||||
BeanClassLoaderAware, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private String persistenceManagerFactoryName;
|
||||
|
||||
private Resource configLocation;
|
||||
|
||||
private final Map<String, Object> jdoPropertyMap = new HashMap<String, Object>();
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
private JdoDialect jdoDialect;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the name of the desired PersistenceManagerFactory.
|
||||
* <p>This may either be a properties resource in the classpath if such a resource
|
||||
* exists, or a PMF definition with that name from "META-INF/jdoconfig.xml",
|
||||
* or a JPA EntityManagerFactory cast to a PersistenceManagerFactory based on the
|
||||
* persistence-unit name from "META-INF/persistence.xml" (JPA).
|
||||
* <p>Default is none: Either 'persistenceManagerFactoryName' or 'configLocation'
|
||||
* or 'jdoProperties' needs to be specified.
|
||||
* @see #setConfigLocation
|
||||
* @see #setJdoProperties
|
||||
*/
|
||||
public void setPersistenceManagerFactoryName(String persistenceManagerFactoryName) {
|
||||
this.persistenceManagerFactoryName = persistenceManagerFactoryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location of the JDO properties config file, for example
|
||||
* as classpath resource "classpath:kodo.properties".
|
||||
* <p>Note: Can be omitted when all necessary properties are
|
||||
* specified locally via this bean.
|
||||
*/
|
||||
public void setConfigLocation(Resource configLocation) {
|
||||
this.configLocation = configLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set JDO properties, such as"javax.jdo.PersistenceManagerFactoryClass".
|
||||
* <p>Can be used to override values in a JDO properties config file,
|
||||
* or to specify all necessary properties locally.
|
||||
* <p>Can be populated with a String "value" (parsed via PropertiesEditor)
|
||||
* or a "props" element in XML bean definitions.
|
||||
*/
|
||||
public void setJdoProperties(Properties jdoProperties) {
|
||||
CollectionUtils.mergePropertiesIntoMap(jdoProperties, this.jdoPropertyMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify JDO properties as a Map, to be passed into
|
||||
* {@code JDOHelper.getPersistenceManagerFactory} (if any).
|
||||
* <p>Can be populated with a "map" or "props" element in XML bean definitions.
|
||||
* @see javax.jdo.JDOHelper#getPersistenceManagerFactory(java.util.Map)
|
||||
*/
|
||||
public void setJdoPropertyMap(Map<String, Object> jdoProperties) {
|
||||
if (jdoProperties != null) {
|
||||
this.jdoPropertyMap.putAll(jdoProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow Map access to the JDO properties to be passed to the JDOHelper,
|
||||
* with the option to add or override specific entries.
|
||||
* <p>Useful for specifying entries directly, for example via
|
||||
* "jdoPropertyMap[myKey]".
|
||||
*/
|
||||
public Map<String, Object> getJdoPropertyMap() {
|
||||
return this.jdoPropertyMap;
|
||||
}
|
||||
/**
|
||||
* Set the JDO dialect to use for the PersistenceExceptionTranslator
|
||||
* functionality of this factory.
|
||||
* <p>Default is a DefaultJdoDialect based on the PersistenceManagerFactory's
|
||||
* underlying DataSource, if any.
|
||||
* @see JdoDialect#translateException
|
||||
* @see #translateExceptionIfPossible
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator
|
||||
*/
|
||||
public void setJdoDialect(JdoDialect jdoDialect) {
|
||||
this.jdoDialect = jdoDialect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the PersistenceManagerFactory for the given location.
|
||||
* @throws IllegalArgumentException in case of illegal property values
|
||||
* @throws IOException if the properties could not be loaded from the given location
|
||||
* @throws JDOException in case of JDO initialization errors
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws IllegalArgumentException, IOException, JDOException {
|
||||
if (this.persistenceManagerFactoryName != null) {
|
||||
if (this.configLocation != null || !this.jdoPropertyMap.isEmpty()) {
|
||||
throw new IllegalStateException("'configLocation'/'jdoProperties' not supported in " +
|
||||
"combination with 'persistenceManagerFactoryName' - specify one or the other, not both");
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Building new JDO PersistenceManagerFactory for name '" +
|
||||
this.persistenceManagerFactoryName + "'");
|
||||
}
|
||||
this.persistenceManagerFactory = newPersistenceManagerFactory(this.persistenceManagerFactoryName);
|
||||
}
|
||||
|
||||
else {
|
||||
Map<String, Object> mergedProps = new HashMap<String, Object>();
|
||||
if (this.configLocation != null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Loading JDO config from [" + this.configLocation + "]");
|
||||
}
|
||||
CollectionUtils.mergePropertiesIntoMap(
|
||||
PropertiesLoaderUtils.loadProperties(this.configLocation), mergedProps);
|
||||
}
|
||||
mergedProps.putAll(this.jdoPropertyMap);
|
||||
logger.info("Building new JDO PersistenceManagerFactory");
|
||||
this.persistenceManagerFactory = newPersistenceManagerFactory(mergedProps);
|
||||
}
|
||||
|
||||
// Build default JdoDialect if none explicitly specified.
|
||||
if (this.jdoDialect == null) {
|
||||
this.jdoDialect = new DefaultJdoDialect(this.persistenceManagerFactory.getConnectionFactory());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this to perform custom initialization of the
|
||||
* PersistenceManagerFactory instance, creating it for the specified name.
|
||||
* <p>The default implementation invokes JDOHelper's
|
||||
* {@code getPersistenceManagerFactory(String)} method.
|
||||
* A custom implementation could prepare the instance in a specific way,
|
||||
* or use a custom PersistenceManagerFactory implementation.
|
||||
* @param name the name of the desired PersistenceManagerFactory
|
||||
* @return the PersistenceManagerFactory instance
|
||||
* @see javax.jdo.JDOHelper#getPersistenceManagerFactory(String)
|
||||
*/
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
|
||||
return JDOHelper.getPersistenceManagerFactory(name, this.beanClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this to perform custom initialization of the
|
||||
* PersistenceManagerFactory instance, creating it via the given Properties
|
||||
* that got prepared by this LocalPersistenceManagerFactoryBean.
|
||||
* <p>The default implementation invokes JDOHelper's
|
||||
* {@code getPersistenceManagerFactory(Map)} method.
|
||||
* A custom implementation could prepare the instance in a specific way,
|
||||
* or use a custom PersistenceManagerFactory implementation.
|
||||
* @param props the merged properties prepared by this LocalPersistenceManagerFactoryBean
|
||||
* @return the PersistenceManagerFactory instance
|
||||
* @see javax.jdo.JDOHelper#getPersistenceManagerFactory(java.util.Map)
|
||||
*/
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(Map<?, ?> props) {
|
||||
return JDOHelper.getPersistenceManagerFactory(props, this.beanClassLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton PersistenceManagerFactory.
|
||||
*/
|
||||
@Override
|
||||
public PersistenceManagerFactory getObject() {
|
||||
return this.persistenceManagerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends PersistenceManagerFactory> getObjectType() {
|
||||
return (this.persistenceManagerFactory != null ?
|
||||
this.persistenceManagerFactory.getClass() : PersistenceManagerFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of the PersistenceExceptionTranslator interface,
|
||||
* as autodetected by Spring's PersistenceExceptionTranslationPostProcessor.
|
||||
* <p>Converts the exception if it is a JDOException, preferably using a specified
|
||||
* JdoDialect. Else returns {@code null} to indicate an unknown exception.
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @see JdoDialect#translateException
|
||||
* @see PersistenceManagerFactoryUtils#convertJdoAccessException
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
if (ex instanceof JDOException) {
|
||||
if (this.jdoDialect != null) {
|
||||
return this.jdoDialect.translateException((JDOException) ex);
|
||||
}
|
||||
else {
|
||||
return PersistenceManagerFactoryUtils.convertJdoAccessException((JDOException) ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the PersistenceManagerFactory on bean factory shutdown.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
logger.info("Closing JDO PersistenceManagerFactory");
|
||||
this.persistenceManagerFactory.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,334 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import javax.jdo.JDODataStoreException;
|
||||
import javax.jdo.JDOException;
|
||||
import javax.jdo.JDOFatalDataStoreException;
|
||||
import javax.jdo.JDOFatalUserException;
|
||||
import javax.jdo.JDOObjectNotFoundException;
|
||||
import javax.jdo.JDOOptimisticVerificationException;
|
||||
import javax.jdo.JDOUserException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
import javax.jdo.Query;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for JDO {@link PersistenceManager} handling,
|
||||
* allowing for reuse of PersistenceManager instances within transactions.
|
||||
* Also provides support for exception translation.
|
||||
*
|
||||
* <p>Used internally by {@link JdoTransactionManager}.
|
||||
* Can also be used directly in application code.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see JdoTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
public abstract class PersistenceManagerFactoryUtils {
|
||||
|
||||
/**
|
||||
* Order value for TransactionSynchronization objects that clean up JDO
|
||||
* PersistenceManagers. Return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100
|
||||
* to execute PersistenceManager cleanup before JDBC Connection cleanup, if any.
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
|
||||
*/
|
||||
public static final int PERSISTENCE_MANAGER_SYNCHRONIZATION_ORDER =
|
||||
DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PersistenceManagerFactoryUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
* Create an appropriate SQLExceptionTranslator for the given PersistenceManagerFactory.
|
||||
* <p>If a DataSource is found, creates a SQLErrorCodeSQLExceptionTranslator for the
|
||||
* DataSource; else, falls back to a SQLStateSQLExceptionTranslator.
|
||||
* @param connectionFactory the connection factory of the PersistenceManagerFactory
|
||||
* (may be {@code null})
|
||||
* @return the SQLExceptionTranslator (never {@code null})
|
||||
* @see javax.jdo.PersistenceManagerFactory#getConnectionFactory()
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
static SQLExceptionTranslator newJdbcExceptionTranslator(Object connectionFactory) {
|
||||
// Check for PersistenceManagerFactory's DataSource.
|
||||
if (connectionFactory instanceof DataSource) {
|
||||
return new SQLErrorCodeSQLExceptionTranslator((DataSource) connectionFactory);
|
||||
}
|
||||
else {
|
||||
return new SQLStateSQLExceptionTranslator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a JDO PersistenceManager via the given factory. Is aware of a
|
||||
* corresponding PersistenceManager bound to the current thread,
|
||||
* for example when using JdoTransactionManager. Will create a new
|
||||
* PersistenceManager else, if "allowCreate" is {@code true}.
|
||||
* @param pmf PersistenceManagerFactory to create the PersistenceManager with
|
||||
* @param allowCreate if a non-transactional PersistenceManager should be created
|
||||
* when no transactional PersistenceManager can be found for the current thread
|
||||
* @return the PersistenceManager
|
||||
* @throws DataAccessResourceFailureException if the PersistenceManager couldn't be obtained
|
||||
* @throws IllegalStateException if no thread-bound PersistenceManager found and
|
||||
* "allowCreate" is {@code false}
|
||||
* @see JdoTransactionManager
|
||||
*/
|
||||
public static PersistenceManager getPersistenceManager(PersistenceManagerFactory pmf, boolean allowCreate)
|
||||
throws DataAccessResourceFailureException, IllegalStateException {
|
||||
|
||||
try {
|
||||
return doGetPersistenceManager(pmf, allowCreate);
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not obtain JDO PersistenceManager", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a JDO PersistenceManager via the given factory. Is aware of a
|
||||
* corresponding PersistenceManager bound to the current thread,
|
||||
* for example when using JdoTransactionManager. Will create a new
|
||||
* PersistenceManager else, if "allowCreate" is {@code true}.
|
||||
* <p>Same as {@code getPersistenceManager}, but throwing the original JDOException.
|
||||
* @param pmf PersistenceManagerFactory to create the PersistenceManager with
|
||||
* @param allowCreate if a non-transactional PersistenceManager should be created
|
||||
* when no transactional PersistenceManager can be found for the current thread
|
||||
* @return the PersistenceManager
|
||||
* @throws JDOException if the PersistenceManager couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound PersistenceManager found and
|
||||
* "allowCreate" is {@code false}
|
||||
* @see #getPersistenceManager(javax.jdo.PersistenceManagerFactory, boolean)
|
||||
* @see JdoTransactionManager
|
||||
*/
|
||||
public static PersistenceManager doGetPersistenceManager(PersistenceManagerFactory pmf, boolean allowCreate)
|
||||
throws JDOException, IllegalStateException {
|
||||
|
||||
Assert.notNull(pmf, "No PersistenceManagerFactory specified");
|
||||
|
||||
PersistenceManagerHolder pmHolder =
|
||||
(PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
|
||||
if (pmHolder != null) {
|
||||
if (!pmHolder.isSynchronizedWithTransaction() &&
|
||||
TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
pmHolder.setSynchronizedWithTransaction(true);
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new PersistenceManagerSynchronization(pmHolder, pmf, false));
|
||||
}
|
||||
return pmHolder.getPersistenceManager();
|
||||
}
|
||||
|
||||
if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
throw new IllegalStateException("No JDO PersistenceManager bound to thread, " +
|
||||
"and configuration does not allow creation of non-transactional one here");
|
||||
}
|
||||
|
||||
logger.debug("Opening JDO PersistenceManager");
|
||||
PersistenceManager pm = pmf.getPersistenceManager();
|
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
logger.debug("Registering transaction synchronization for JDO PersistenceManager");
|
||||
// Use same PersistenceManager for further JDO actions within the transaction.
|
||||
// Thread object will get removed by synchronization at transaction completion.
|
||||
pmHolder = new PersistenceManagerHolder(pm);
|
||||
pmHolder.setSynchronizedWithTransaction(true);
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new PersistenceManagerSynchronization(pmHolder, pmf, true));
|
||||
TransactionSynchronizationManager.bindResource(pmf, pmHolder);
|
||||
}
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given JDO PersistenceManager is transactional, that is,
|
||||
* bound to the current thread by Spring's transaction facilities.
|
||||
* @param pm the JDO PersistenceManager to check
|
||||
* @param pmf JDO PersistenceManagerFactory that the PersistenceManager
|
||||
* was created with (can be {@code null})
|
||||
* @return whether the PersistenceManager is transactional
|
||||
*/
|
||||
public static boolean isPersistenceManagerTransactional(
|
||||
PersistenceManager pm, PersistenceManagerFactory pmf) {
|
||||
|
||||
if (pmf == null) {
|
||||
return false;
|
||||
}
|
||||
PersistenceManagerHolder pmHolder =
|
||||
(PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
|
||||
return (pmHolder != null && pm == pmHolder.getPersistenceManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the current transaction timeout, if any, to the given JDO Query object.
|
||||
* @param query the JDO Query object
|
||||
* @param pmf JDO PersistenceManagerFactory that the Query was created for
|
||||
* @throws JDOException if thrown by JDO methods
|
||||
*/
|
||||
public static void applyTransactionTimeout(Query query, PersistenceManagerFactory pmf) throws JDOException {
|
||||
Assert.notNull(query, "No Query object specified");
|
||||
PersistenceManagerHolder pmHolder =
|
||||
(PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
|
||||
if (pmHolder != null && pmHolder.hasTimeout() &&
|
||||
pmf.supportedOptions().contains("javax.jdo.option.DatastoreTimeout")) {
|
||||
int timeout = (int) pmHolder.getTimeToLiveInMillis();
|
||||
query.setDatastoreReadTimeoutMillis(timeout);
|
||||
query.setDatastoreWriteTimeoutMillis(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given JDOException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy.
|
||||
* <p>The most important cases like object not found or optimistic locking failure
|
||||
* are covered here. For more fine-granular conversion, JdoTransactionManager
|
||||
* supports sophisticated translation of exceptions via a JdoDialect.
|
||||
* @param ex JDOException that occured
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see JdoTransactionManager#convertJdoAccessException
|
||||
* @see JdoDialect#translateException
|
||||
*/
|
||||
public static DataAccessException convertJdoAccessException(JDOException ex) {
|
||||
if (ex instanceof JDOObjectNotFoundException) {
|
||||
throw new JdoObjectRetrievalFailureException((JDOObjectNotFoundException) ex);
|
||||
}
|
||||
if (ex instanceof JDOOptimisticVerificationException) {
|
||||
throw new JdoOptimisticLockingFailureException((JDOOptimisticVerificationException) ex);
|
||||
}
|
||||
if (ex instanceof JDODataStoreException) {
|
||||
return new JdoResourceFailureException((JDODataStoreException) ex);
|
||||
}
|
||||
if (ex instanceof JDOFatalDataStoreException) {
|
||||
return new JdoResourceFailureException((JDOFatalDataStoreException) ex);
|
||||
}
|
||||
if (ex instanceof JDOUserException) {
|
||||
return new JdoUsageException((JDOUserException) ex);
|
||||
}
|
||||
if (ex instanceof JDOFatalUserException) {
|
||||
return new JdoUsageException((JDOFatalUserException) ex);
|
||||
}
|
||||
// fallback
|
||||
return new JdoSystemException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given PersistenceManager, created via the given factory,
|
||||
* if it is not managed externally (i.e. not bound to the thread).
|
||||
* @param pm PersistenceManager to close
|
||||
* @param pmf PersistenceManagerFactory that the PersistenceManager was created with
|
||||
* (can be {@code null})
|
||||
*/
|
||||
public static void releasePersistenceManager(PersistenceManager pm, PersistenceManagerFactory pmf) {
|
||||
try {
|
||||
doReleasePersistenceManager(pm, pmf);
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
logger.debug("Could not close JDO PersistenceManager", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Unexpected exception on closing JDO PersistenceManager", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually release a PersistenceManager for the given factory.
|
||||
* Same as {@code releasePersistenceManager}, but throwing the original JDOException.
|
||||
* @param pm PersistenceManager to close
|
||||
* @param pmf PersistenceManagerFactory that the PersistenceManager was created with
|
||||
* (can be {@code null})
|
||||
* @throws JDOException if thrown by JDO methods
|
||||
*/
|
||||
public static void doReleasePersistenceManager(PersistenceManager pm, PersistenceManagerFactory pmf)
|
||||
throws JDOException {
|
||||
|
||||
if (pm == null) {
|
||||
return;
|
||||
}
|
||||
// Only release non-transactional PersistenceManagers.
|
||||
if (!isPersistenceManagerTransactional(pm, pmf)) {
|
||||
logger.debug("Closing JDO PersistenceManager");
|
||||
pm.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for resource cleanup at the end of a non-JDO transaction
|
||||
* (e.g. when participating in a JtaTransactionManager transaction).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
private static class PersistenceManagerSynchronization
|
||||
extends ResourceHolderSynchronization<PersistenceManagerHolder, PersistenceManagerFactory>
|
||||
implements Ordered {
|
||||
|
||||
private final boolean newPersistenceManager;
|
||||
|
||||
public PersistenceManagerSynchronization(
|
||||
PersistenceManagerHolder pmHolder, PersistenceManagerFactory pmf, boolean newPersistenceManager) {
|
||||
super(pmHolder, pmf);
|
||||
this.newPersistenceManager = newPersistenceManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PERSISTENCE_MANAGER_SYNCHRONIZATION_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushResource(PersistenceManagerHolder resourceHolder) {
|
||||
try {
|
||||
resourceHolder.getPersistenceManager().flush();
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw convertJdoAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUnbindAtCompletion() {
|
||||
return this.newPersistenceManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldReleaseAfterCompletion(PersistenceManagerHolder resourceHolder) {
|
||||
return !resourceHolder.getPersistenceManager().isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseResource(PersistenceManagerHolder resourceHolder, PersistenceManagerFactory resourceKey) {
|
||||
releasePersistenceManager(resourceHolder.getPersistenceManager(), resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
import javax.jdo.PersistenceManager;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Holder wrapping a JDO PersistenceManager.
|
||||
* JdoTransactionManager binds instances of this class
|
||||
* to the thread, for a given PersistenceManagerFactory.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 03.06.2003
|
||||
* @see JdoTransactionManager
|
||||
* @see PersistenceManagerFactoryUtils
|
||||
*/
|
||||
public class PersistenceManagerHolder extends ResourceHolderSupport {
|
||||
|
||||
private final PersistenceManager persistenceManager;
|
||||
|
||||
private boolean transactionActive;
|
||||
|
||||
|
||||
public PersistenceManagerHolder(PersistenceManager persistenceManager) {
|
||||
Assert.notNull(persistenceManager, "PersistenceManager must not be null");
|
||||
this.persistenceManager = persistenceManager;
|
||||
}
|
||||
|
||||
|
||||
public PersistenceManager getPersistenceManager() {
|
||||
return this.persistenceManager;
|
||||
}
|
||||
|
||||
protected void setTransactionActive(boolean transactionActive) {
|
||||
this.transactionActive = transactionActive;
|
||||
}
|
||||
|
||||
protected boolean isTransactionActive() {
|
||||
return this.transactionActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.transactionActive = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
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;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
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 the single OpenPersistenceManagerInView
|
||||
* PersistenceManager) on {@code getPersistenceManager()}, if any.
|
||||
*
|
||||
* <p>Essentially, {@code getPersistenceManager()} calls get seamlessly
|
||||
* forwarded to {@link PersistenceManagerFactoryUtils#getPersistenceManager}.
|
||||
* Furthermore, {@code PersistenceManager.close} calls get forwarded to
|
||||
* {@link PersistenceManagerFactoryUtils#releasePersistenceManager}.
|
||||
*
|
||||
* <p>The main advantage of this proxy is that it allows DAOs to work with a
|
||||
* plain JDO PersistenceManagerFactory reference, while still participating in
|
||||
* Spring's (or a J2EE server's) resource and transaction management. DAOs will
|
||||
* only rely on the JDO API in such a scenario, without any Spring dependencies.
|
||||
*
|
||||
* <p>Note that the behavior of this proxy matches the behavior that the JDO spec
|
||||
* defines for a PersistenceManagerFactory as exposed by a JCA connector, when
|
||||
* deployed in a J2EE server. Hence, DAOs could seamlessly switch between a JNDI
|
||||
* PersistenceManagerFactory and this proxy for a local PersistenceManagerFactory,
|
||||
* receiving the reference through Dependency Injection. This will work without
|
||||
* any Spring API dependencies in the DAO code!
|
||||
*
|
||||
* <p>Of course, you can still access the target PersistenceManagerFactory
|
||||
* even when your DAOs go through this proxy, by defining a bean reference
|
||||
* that points directly at your target PersistenceManagerFactory bean.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see javax.jdo.PersistenceManagerFactory#getPersistenceManager()
|
||||
* @see javax.jdo.PersistenceManager#close()
|
||||
* @see PersistenceManagerFactoryUtils#getPersistenceManager
|
||||
* @see PersistenceManagerFactoryUtils#releasePersistenceManager
|
||||
*/
|
||||
public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBean<PersistenceManagerFactory> {
|
||||
|
||||
private PersistenceManagerFactory target;
|
||||
|
||||
private boolean allowCreate = true;
|
||||
|
||||
private PersistenceManagerFactory 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 setTargetPersistenceManagerFactory(PersistenceManagerFactory target) {
|
||||
Assert.notNull(target, "Target PersistenceManagerFactory must not be null");
|
||||
this.target = target;
|
||||
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(target.getClass(), target.getClass().getClassLoader());
|
||||
this.proxy = (PersistenceManagerFactory) Proxy.newProxyInstance(
|
||||
target.getClass().getClassLoader(), ifcs, new PersistenceManagerFactoryInvocationHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target JDO PersistenceManagerFactory that this proxy delegates to.
|
||||
*/
|
||||
public PersistenceManagerFactory getTargetPersistenceManagerFactory() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the PersistenceManagerFactory proxy is allowed to create
|
||||
* a non-transactional PersistenceManager when no transactional
|
||||
* PersistenceManager can be found for the current thread.
|
||||
* <p>Default is "true". Can be turned off to enforce access to
|
||||
* transactional PersistenceManagers, which safely allows for DAOs
|
||||
* written to get a PersistenceManager without explicit closing
|
||||
* (i.e. a {@code PersistenceManagerFactory.getPersistenceManager()}
|
||||
* call without corresponding {@code PersistenceManager.close()} call).
|
||||
* @see 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 PersistenceManagerFactory getObject() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends PersistenceManagerFactory> getObjectType() {
|
||||
return PersistenceManagerFactory.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that delegates getPersistenceManager calls on the
|
||||
* PersistenceManagerFactory proxy to PersistenceManagerFactoryUtils
|
||||
* for being aware of thread-bound transactions.
|
||||
*/
|
||||
private class PersistenceManagerFactoryInvocationHandler implements InvocationHandler {
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Invocation on PersistenceManagerFactory 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 PersistenceManagerFactory proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
}
|
||||
else if (method.getName().equals("getPersistenceManager")) {
|
||||
PersistenceManagerFactory target = getTargetPersistenceManagerFactory();
|
||||
PersistenceManager pm =
|
||||
PersistenceManagerFactoryUtils.doGetPersistenceManager(target, isAllowCreate());
|
||||
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), pm.getClass().getClassLoader());
|
||||
return Proxy.newProxyInstance(
|
||||
pm.getClass().getClassLoader(), ifcs, new PersistenceManagerInvocationHandler(pm, target));
|
||||
}
|
||||
|
||||
// Invoke method on target PersistenceManagerFactory.
|
||||
try {
|
||||
return method.invoke(getTargetPersistenceManagerFactory(), args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that delegates close calls on PersistenceManagers to
|
||||
* PersistenceManagerFactoryUtils for being aware of thread-bound transactions.
|
||||
*/
|
||||
private static class PersistenceManagerInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final PersistenceManager target;
|
||||
|
||||
private final PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
public PersistenceManagerInvocationHandler(PersistenceManager target, PersistenceManagerFactory pmf) {
|
||||
this.target = target;
|
||||
this.persistenceManagerFactory = pmf;
|
||||
}
|
||||
|
||||
@Override
|
||||
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("close")) {
|
||||
// Handle close method: only close if not within a transaction.
|
||||
PersistenceManagerFactoryUtils.doReleasePersistenceManager(
|
||||
this.target, this.persistenceManagerFactory);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Invoke method on target PersistenceManager.
|
||||
try {
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Package providing integration of JDO (Java Date Objects) with Spring concepts.
|
||||
* Contains PersistenceManagerFactory helper classes, a template plus callback for JDO
|
||||
* access, and an implementation of Spring's transaction SPI for local JDO transactions.
|
||||
*/
|
||||
package org.springframework.orm.jdo;
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.io.IOException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.orm.jdo.PersistenceManagerFactoryUtils;
|
||||
import org.springframework.orm.jdo.PersistenceManagerHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Servlet Filter that binds a JDO PersistenceManager to the thread for the
|
||||
* entire processing of the request. Intended for the "Open PersistenceManager in
|
||||
* View" pattern, i.e. to allow for lazy loading in web views despite the
|
||||
* original transactions already being completed.
|
||||
*
|
||||
* <p>This filter makes JDO PersistenceManagers available via the current thread,
|
||||
* which will be autodetected by transaction managers. It is suitable for service
|
||||
* layer transactions via {@link org.springframework.orm.jdo.JdoTransactionManager}
|
||||
* or {@link org.springframework.transaction.jta.JtaTransactionManager} as well
|
||||
* as for non-transactional read-only execution.
|
||||
*
|
||||
* <p>Looks up the PersistenceManagerFactory in Spring's root web application context.
|
||||
* Supports a "persistenceManagerFactoryBeanName" filter init-param in {@code web.xml};
|
||||
* the default bean name is "persistenceManagerFactory".
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see OpenPersistenceManagerInViewInterceptor
|
||||
* @see org.springframework.orm.jdo.JdoTransactionManager
|
||||
* @see org.springframework.orm.jdo.PersistenceManagerFactoryUtils#getPersistenceManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
public class OpenPersistenceManagerInViewFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String DEFAULT_PERSISTENCE_MANAGER_FACTORY_BEAN_NAME = "persistenceManagerFactory";
|
||||
|
||||
private String persistenceManagerFactoryBeanName = DEFAULT_PERSISTENCE_MANAGER_FACTORY_BEAN_NAME;
|
||||
|
||||
|
||||
/**
|
||||
* Set the bean name of the PersistenceManagerFactory to fetch from Spring's
|
||||
* root application context. Default is "persistenceManagerFactory".
|
||||
* @see #DEFAULT_PERSISTENCE_MANAGER_FACTORY_BEAN_NAME
|
||||
*/
|
||||
public void setPersistenceManagerFactoryBeanName(String persistenceManagerFactoryBeanName) {
|
||||
this.persistenceManagerFactoryBeanName = persistenceManagerFactoryBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean name of the PersistenceManagerFactory to fetch from Spring's
|
||||
* root application context.
|
||||
*/
|
||||
protected String getPersistenceManagerFactoryBeanName() {
|
||||
return this.persistenceManagerFactoryBeanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may re-bind the opened {@code PersistenceManager}
|
||||
* to each asynchronously dispatched thread and postpone closing it until the very
|
||||
* last asynchronous dispatch.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterAsyncDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may provide an {@code PersistenceManager}
|
||||
* to each error dispatches.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterErrorDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
PersistenceManagerFactory pmf = lookupPersistenceManagerFactory(request);
|
||||
boolean participate = false;
|
||||
|
||||
if (TransactionSynchronizationManager.hasResource(pmf)) {
|
||||
// Do not modify the PersistenceManager: just set the participate flag.
|
||||
participate = true;
|
||||
}
|
||||
else {
|
||||
logger.debug("Opening JDO PersistenceManager in OpenPersistenceManagerInViewFilter");
|
||||
PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
|
||||
}
|
||||
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
finally {
|
||||
if (!participate) {
|
||||
PersistenceManagerHolder pmHolder = (PersistenceManagerHolder)
|
||||
TransactionSynchronizationManager.unbindResource(pmf);
|
||||
logger.debug("Closing JDO PersistenceManager in OpenPersistenceManagerInViewFilter");
|
||||
PersistenceManagerFactoryUtils.releasePersistenceManager(pmHolder.getPersistenceManager(), pmf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the PersistenceManagerFactory that this filter should use,
|
||||
* taking the current HTTP request as argument.
|
||||
* <p>Default implementation delegates to the {@code lookupPersistenceManagerFactory}
|
||||
* without arguments.
|
||||
* @return the PersistenceManagerFactory to use
|
||||
* @see #lookupPersistenceManagerFactory()
|
||||
*/
|
||||
protected PersistenceManagerFactory lookupPersistenceManagerFactory(HttpServletRequest request) {
|
||||
return lookupPersistenceManagerFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the PersistenceManagerFactory that this filter should use.
|
||||
* The default implementation looks for a bean with the specified name
|
||||
* in Spring's root application context.
|
||||
* @return the PersistenceManagerFactory to use
|
||||
* @see #getPersistenceManagerFactoryBeanName
|
||||
*/
|
||||
protected PersistenceManagerFactory lookupPersistenceManagerFactory() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using PersistenceManagerFactory '" + getPersistenceManagerFactoryBeanName() +
|
||||
"' for OpenPersistenceManagerInViewFilter");
|
||||
}
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
|
||||
return wac.getBean(getPersistenceManagerFactoryBeanName(), PersistenceManagerFactory.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jdo.support;
|
||||
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.orm.jdo.PersistenceManagerFactoryUtils;
|
||||
import org.springframework.orm.jdo.PersistenceManagerHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||
|
||||
/**
|
||||
* Spring web request interceptor that binds a JDO PersistenceManager to the
|
||||
* thread for the entire processing of the request. Intended for the "Open
|
||||
* PersistenceManager in View" pattern, i.e. to allow for lazy loading in
|
||||
* web views despite the original transactions already being completed.
|
||||
*
|
||||
* <p>This interceptor makes JDO PersistenceManagers available via the current thread,
|
||||
* which will be autodetected by transaction managers. It is suitable for service
|
||||
* layer transactions via {@link org.springframework.orm.jdo.JdoTransactionManager}
|
||||
* or {@link org.springframework.transaction.jta.JtaTransactionManager} as well
|
||||
* as for non-transactional read-only execution.
|
||||
*
|
||||
* <p>In contrast to {@link OpenPersistenceManagerInViewFilter}, this interceptor
|
||||
* is set up in a Spring application context and can thus take advantage of
|
||||
* bean wiring.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see OpenPersistenceManagerInViewFilter
|
||||
* @see org.springframework.orm.jdo.JdoTransactionManager
|
||||
* @see org.springframework.orm.jdo.PersistenceManagerFactoryUtils#getPersistenceManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
public class OpenPersistenceManagerInViewInterceptor implements WebRequestInterceptor {
|
||||
|
||||
/**
|
||||
* Suffix that gets appended to the PersistenceManagerFactory toString
|
||||
* representation for the "participate in existing persistence manager
|
||||
* handling" request attribute.
|
||||
* @see #getParticipateAttributeName
|
||||
*/
|
||||
public static final String PARTICIPATE_SUFFIX = ".PARTICIPATE";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the JDO PersistenceManagerFactory that should be used to create
|
||||
* PersistenceManagers.
|
||||
*/
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
|
||||
this.persistenceManagerFactory = pmf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDO PersistenceManagerFactory that should be used to create
|
||||
* PersistenceManagers.
|
||||
*/
|
||||
public PersistenceManagerFactory getPersistenceManagerFactory() {
|
||||
return persistenceManagerFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void preHandle(WebRequest request) throws DataAccessException {
|
||||
if (TransactionSynchronizationManager.hasResource(getPersistenceManagerFactory())) {
|
||||
// Do not modify the PersistenceManager: just mark the request accordingly.
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
int newCount = (count != null ? count + 1 : 1);
|
||||
request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
logger.debug("Opening JDO PersistenceManager in OpenPersistenceManagerInViewInterceptor");
|
||||
PersistenceManager pm =
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(getPersistenceManagerFactory(), true);
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getPersistenceManagerFactory(), new PersistenceManagerHolder(pm));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(WebRequest request, ModelMap model) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
if (count != null) {
|
||||
// Do not modify the PersistenceManager: just clear the marker.
|
||||
if (count > 1) {
|
||||
request.setAttribute(participateAttributeName, count - 1, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
request.removeAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PersistenceManagerHolder pmHolder = (PersistenceManagerHolder)
|
||||
TransactionSynchronizationManager.unbindResource(getPersistenceManagerFactory());
|
||||
logger.debug("Closing JDO PersistenceManager in OpenPersistenceManagerInViewInterceptor");
|
||||
PersistenceManagerFactoryUtils.releasePersistenceManager(
|
||||
pmHolder.getPersistenceManager(), getPersistenceManagerFactory());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request is
|
||||
* already filtered. Default implementation takes the toString representation
|
||||
* of the PersistenceManagerFactory instance and appends ".FILTERED".
|
||||
* @see #PARTICIPATE_SUFFIX
|
||||
*/
|
||||
protected String getParticipateAttributeName() {
|
||||
return getPersistenceManagerFactory().toString() + PARTICIPATE_SUFFIX;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.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.PersistenceManagerFactory;
|
||||
import javax.jdo.Query;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.orm.jdo.DefaultJdoDialect;
|
||||
import org.springframework.orm.jdo.JdoDialect;
|
||||
import org.springframework.orm.jdo.PersistenceManagerFactoryUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Proxy that implements the {@link javax.jdo.PersistenceManager} interface,
|
||||
* delegating to the current thread-bound PersistenceManager (the Spring-managed
|
||||
* transactional PersistenceManager or the single OpenPersistenceManagerInView
|
||||
* PersistenceManager, if any) on each invocation. This class makes such a
|
||||
* Spring-style PersistenceManager proxy available for bean references.
|
||||
*
|
||||
* <p>The main advantage of this proxy is that it allows DAOs to work with a
|
||||
* plain JDO PersistenceManager reference in JDO 3.0 style
|
||||
* (see {@link javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()}),
|
||||
* while still participating in Spring's resource and transaction management.
|
||||
*
|
||||
* <p>The behavior of this proxy matches the behavior that the JDO 3.0 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!
|
||||
*
|
||||
* @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 implements FactoryBean<PersistenceManager>, InitializingBean {
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
private JdoDialect jdoDialect;
|
||||
|
||||
private Class<? extends PersistenceManager> persistenceManagerInterface = PersistenceManager.class;
|
||||
|
||||
private boolean allowCreate = true;
|
||||
|
||||
private PersistenceManager proxy;
|
||||
|
||||
|
||||
/**
|
||||
* Set the target PersistenceManagerFactory for this proxy.
|
||||
*/
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory persistenceManagerFactory) {
|
||||
this.persistenceManagerFactory = persistenceManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target PersistenceManagerFactory for this proxy.
|
||||
*/
|
||||
protected PersistenceManagerFactory getPersistenceManagerFactory() {
|
||||
return this.persistenceManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDO dialect to use for this proxy.
|
||||
* <p>Default is a DefaultJdoDialect based on the PersistenceManagerFactory's
|
||||
* underlying DataSource, if any.
|
||||
*/
|
||||
public void setJdoDialect(JdoDialect jdoDialect) {
|
||||
this.jdoDialect = jdoDialect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDO dialect to use for this proxy.
|
||||
*/
|
||||
protected JdoDialect getJdoDialect() {
|
||||
return this.jdoDialect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the PersistenceManager interface to expose,
|
||||
* possibly including vendor extensions.
|
||||
* <p>Default is the standard {@code javax.jdo.PersistenceManager} interface.
|
||||
*/
|
||||
public void setPersistenceManagerInterface(Class<? extends PersistenceManager> persistenceManagerInterface) {
|
||||
this.persistenceManagerInterface = persistenceManagerInterface;
|
||||
Assert.notNull(persistenceManagerInterface, "persistenceManagerInterface must not be null");
|
||||
Assert.isAssignable(PersistenceManager.class, persistenceManagerInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistenceManager interface to expose.
|
||||
*/
|
||||
protected Class<? extends PersistenceManager> getPersistenceManagerInterface() {
|
||||
return this.persistenceManagerInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the PersistenceManagerFactory proxy is allowed to create
|
||||
* a non-transactional PersistenceManager when no transactional
|
||||
* PersistenceManager can be found for the current thread.
|
||||
* <p>Default is "true". Can be turned off to enforce access to
|
||||
* transactional PersistenceManagers, which safely allows for DAOs
|
||||
* written to get a PersistenceManager without explicit closing
|
||||
* (i.e. a {@code PersistenceManagerFactory.getPersistenceManager()}
|
||||
* call without corresponding {@code 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() {
|
||||
if (getPersistenceManagerFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'persistenceManagerFactory' is required");
|
||||
}
|
||||
// Build default JdoDialect if none explicitly specified.
|
||||
if (this.jdoDialect == null) {
|
||||
this.jdoDialect = new DefaultJdoDialect(getPersistenceManagerFactory().getConnectionFactory());
|
||||
}
|
||||
this.proxy = (PersistenceManager) Proxy.newProxyInstance(
|
||||
getPersistenceManagerFactory().getClass().getClassLoader(),
|
||||
new Class<?>[] {getPersistenceManagerInterface()}, new PersistenceManagerInvocationHandler());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PersistenceManager getObject() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends PersistenceManager> getObjectType() {
|
||||
return getPersistenceManagerInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
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 {
|
||||
|
||||
@Override
|
||||
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());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
finally {
|
||||
PersistenceManagerFactoryUtils.doReleasePersistenceManager(pm, getPersistenceManagerFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 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 3.0 specification. This class makes such a standard
|
||||
* JDO PersistenceManager proxy available for bean references.
|
||||
*
|
||||
* <p>The main advantage of this proxy is that it allows DAOs to work with a
|
||||
* plain JDO PersistenceManager reference in JDO 3.0 style
|
||||
* (see {@link javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()}),
|
||||
* exposing the exact behavior that the target JDO provider implements.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see SpringPersistenceManagerProxyBean
|
||||
* @see javax.jdo.PersistenceManagerFactory#getPersistenceManagerProxy()
|
||||
*/
|
||||
public class StandardPersistenceManagerProxyBean implements FactoryBean<PersistenceManager> {
|
||||
|
||||
private PersistenceManager proxy;
|
||||
|
||||
|
||||
/**
|
||||
* Set the target JDO PersistenceManagerFactory that this proxy should
|
||||
* delegate to. This should be the raw PersistenceManagerFactory, as
|
||||
* accessed by JdoTransactionManager.
|
||||
* @see org.springframework.orm.jdo.JdoTransactionManager
|
||||
*/
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
|
||||
Assert.notNull(pmf, "PersistenceManagerFactory must not be null");
|
||||
this.proxy = pmf.getPersistenceManagerProxy();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PersistenceManager getObject() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends PersistenceManager> getObjectType() {
|
||||
return (this.proxy != null ? this.proxy.getClass() : PersistenceManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Classes supporting the {@code org.springframework.orm.jdo} package.
|
||||
*/
|
||||
package org.springframework.orm.jdo.support;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Spring's O/R Mapping package: supporting Hibernate, JPA, JDO, and iBATIS SQL Maps.
|
||||
Spring's O/R Mapping package: supporting JPA as well as native Hibernate.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user