parent
2b3445df81
commit
d341624e91
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,14 +20,12 @@ import java.sql.Connection;
|
|||
|
||||
/**
|
||||
* Simple interface to be implemented by handles for a JDBC Connection.
|
||||
* Used by JpaDialect and JdoDialect, for example.
|
||||
* Used by JpaDialect, for example.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see SimpleConnectionHandle
|
||||
* @see ConnectionHolder
|
||||
* @see org.springframework.orm.jdo.JpaDialect#getJdbcConnection
|
||||
* @see org.springframework.orm.jdo.JdoDialect#getJdbcConnection
|
||||
*/
|
||||
public interface ConnectionHandle {
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -182,9 +182,7 @@ public class ConnectionHolder extends ResourceHolderSupport {
|
|||
* <p>This is necessary for ConnectionHandles that expect "Connection borrowing",
|
||||
* where each returned Connection is only temporarily leased and needs to be
|
||||
* returned once the data operation is done, to make the Connection available
|
||||
* for other operations within the same transaction. This is the case with
|
||||
* JDO 2.0 DataStoreConnections, for example.
|
||||
* @see org.springframework.orm.jdo.DefaultJdoDialect#getJdbcConnection
|
||||
* for other operations within the same transaction.
|
||||
*/
|
||||
@Override
|
||||
public void released() {
|
||||
|
|
|
@ -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>
|
|
@ -1,796 +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.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Savepoint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.jdo.Constants;
|
||||
import javax.jdo.JDOFatalDataStoreException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
import javax.jdo.Transaction;
|
||||
import javax.sql.DataSource;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.jdbc.datasource.ConnectionHandle;
|
||||
import org.springframework.jdbc.datasource.ConnectionHolder;
|
||||
import org.springframework.jdbc.datasource.SimpleConnectionHandle;
|
||||
import org.springframework.orm.jdo.support.SpringPersistenceManagerProxyBean;
|
||||
import org.springframework.orm.jdo.support.StandardPersistenceManagerProxyBean;
|
||||
import org.springframework.tests.transaction.MockJtaTransaction;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JdoTransactionManagerTests {
|
||||
|
||||
private PersistenceManagerFactory pmf;
|
||||
|
||||
private PersistenceManager pm;
|
||||
|
||||
private Transaction tx;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
pmf = mock(PersistenceManagerFactory.class);
|
||||
pm = mock(PersistenceManager.class);
|
||||
tx = mock(Transaction.class);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommit() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pmf.getPersistenceManagerProxy()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
TransactionAwarePersistenceManagerFactoryProxy proxyFactory =
|
||||
new TransactionAwarePersistenceManagerFactoryProxy();
|
||||
proxyFactory.setTargetPersistenceManagerFactory(pmf);
|
||||
PersistenceManagerFactory pmfProxy = proxyFactory.getObject();
|
||||
assertEquals(pm.toString(), pmfProxy.getPersistenceManager().toString());
|
||||
pmfProxy.getPersistenceManager().flush();
|
||||
pmfProxy.getPersistenceManager().close();
|
||||
|
||||
SpringPersistenceManagerProxyBean proxyBean = new SpringPersistenceManagerProxyBean();
|
||||
proxyBean.setPersistenceManagerFactory(pmf);
|
||||
proxyBean.afterPropertiesSet();
|
||||
PersistenceManager pmProxy = proxyBean.getObject();
|
||||
assertSame(pmf, pmProxy.getPersistenceManagerFactory());
|
||||
pmProxy.flush();
|
||||
pmProxy.close();
|
||||
|
||||
StandardPersistenceManagerProxyBean stdProxyBean = new StandardPersistenceManagerProxyBean();
|
||||
stdProxyBean.setPersistenceManagerFactory(pmf);
|
||||
PersistenceManager stdPmProxy = stdProxyBean.getObject();
|
||||
stdPmProxy.flush();
|
||||
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(pm, times(4)).flush();
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionRollback() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
try {
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
throw new RuntimeException("application exception");
|
||||
}
|
||||
});
|
||||
fail("Should have thrown RuntimeException");
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).rollback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionRollbackWithAlreadyRolledBack() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
try {
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
throw new RuntimeException("application exception");
|
||||
}
|
||||
});
|
||||
fail("Should have thrown RuntimeException");
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionRollbackOnly() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).rollback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingTransactionWithCommit() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
final TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingTransactionWithRollback() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
final TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
try {
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
throw new RuntimeException("application exception");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
fail("Should have thrown RuntimeException");
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
// expected
|
||||
}
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).setRollbackOnly();
|
||||
verify(tx).rollback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingTransactionWithRollbackOnly() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
given(tx.getRollbackOnly()).willReturn(true);
|
||||
willThrow(new JDOFatalDataStoreException()).given(tx).commit();
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
final TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
|
||||
try {
|
||||
tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
status.setRollbackOnly();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
fail("Should have thrown JdoResourceFailureException");
|
||||
}
|
||||
catch (JdoResourceFailureException ex) {
|
||||
// expected
|
||||
}
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).setRollbackOnly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingTransactionWithWithRequiresNew() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
final TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
verify(tx, times(2)).begin();
|
||||
verify(tx, times(2)).commit();
|
||||
verify(pm).flush();
|
||||
verify(pm, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingTransactionWithWithRequiresNewAndPrebound() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(tx.isActive()).willReturn(true);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
final TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
TransactionSynchronizationManager.unbindResource(pmf);
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(tx, times(2)).begin();
|
||||
verify(tx, times(2)).commit();
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJtaTransactionCommit() throws Exception {
|
||||
UserTransaction ut = mock(UserTransaction.class);
|
||||
given(ut.getStatus()).willReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE);
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager(ut);
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(ut).begin();
|
||||
verify(ut).commit();
|
||||
verify(pm, times(2)).flush();
|
||||
verify(pm, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParticipatingJtaTransactionWithWithRequiresNewAndPrebound() throws Exception {
|
||||
final UserTransaction ut = mock(UserTransaction.class);
|
||||
final TransactionManager tm = mock(TransactionManager.class);
|
||||
|
||||
given(ut.getStatus()).willReturn(Status.STATUS_NO_TRANSACTION,
|
||||
Status.STATUS_ACTIVE, Status.STATUS_ACTIVE, Status.STATUS_ACTIVE,
|
||||
Status.STATUS_ACTIVE, Status.STATUS_ACTIVE);
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
|
||||
final TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
try {
|
||||
MockJtaTransaction transaction = new MockJtaTransaction();
|
||||
given(tm.suspend()).willReturn(transaction);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
|
||||
return tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
TransactionSynchronizationManager.unbindResource(pmf);
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(ut, times(2)).begin();
|
||||
verify(pm).flush();
|
||||
verify(pm, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithPropagationSupports() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Is not new transaction", !status.isNewTransaction());
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
verify(pm, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsolationLevel() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
}
|
||||
});
|
||||
verify(tx).setIsolationLevel(Constants.TX_SERIALIZABLE);
|
||||
verify(pm).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithPrebound() {
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
TransactionSynchronizationManager.unbindResource(pmf);
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
verify(tx).begin();
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithDataSource() throws SQLException {
|
||||
final DataSource ds = mock(DataSource.class);
|
||||
JdoDialect dialect = mock(JdoDialect.class);
|
||||
final Connection con = mock(Connection.class);
|
||||
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
|
||||
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
TransactionTemplate tt = new TransactionTemplate();
|
||||
given(dialect.getJdbcConnection(pm, false)).willReturn(conHandle);
|
||||
|
||||
JdoTransactionManager tm = new JdoTransactionManager();
|
||||
tm.setPersistenceManagerFactory(pmf);
|
||||
tm.setDataSource(ds);
|
||||
tm.setJdoDialect(dialect);
|
||||
tt.setTransactionManager(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
|
||||
|
||||
verify(pm).close();
|
||||
verify(dialect).beginTransaction(tx, tt);
|
||||
verify(dialect).releaseJdbcConnection(conHandle, pm);
|
||||
verify(dialect).cleanupTransaction(null);
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithAutoDetectedDataSource() throws SQLException {
|
||||
final DataSource ds = mock(DataSource.class);
|
||||
JdoDialect dialect = mock(JdoDialect.class);
|
||||
final Connection con = mock(Connection.class);
|
||||
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
|
||||
|
||||
given(pmf.getConnectionFactory()).willReturn(ds);
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
TransactionTemplate tt = new TransactionTemplate();
|
||||
given(dialect.getJdbcConnection(pm, false)).willReturn(conHandle);
|
||||
|
||||
JdoTransactionManager tm = new JdoTransactionManager();
|
||||
tm.setPersistenceManagerFactory(pmf);
|
||||
tm.setJdoDialect(dialect);
|
||||
tm.afterPropertiesSet();
|
||||
tt.setTransactionManager(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
|
||||
|
||||
verify(pm).close();
|
||||
verify(dialect).beginTransaction(tx, tt);
|
||||
verify(dialect).releaseJdbcConnection(conHandle, pm);
|
||||
verify(dialect).cleanupTransaction(null);
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithAutoDetectedDataSourceAndNoConnection() throws SQLException {
|
||||
final DataSource ds = mock(DataSource.class);
|
||||
final JdoDialect dialect = mock(JdoDialect.class);
|
||||
|
||||
given(pmf.getConnectionFactory()).willReturn(ds);
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
TransactionTemplate tt = new TransactionTemplate();
|
||||
given(dialect.getJdbcConnection(pm, false)).willReturn(null);
|
||||
|
||||
JdoTransactionManager tm = new JdoTransactionManager();
|
||||
tm.setPersistenceManagerFactory(pmf);
|
||||
tm.setJdoDialect(dialect);
|
||||
tm.afterPropertiesSet();
|
||||
tt.setTransactionManager(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
|
||||
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(dialect).beginTransaction(tx, tt);
|
||||
verify(dialect).cleanupTransaction(null);
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingTransactionWithPropagationNestedAndRollback() throws SQLException {
|
||||
doTestExistingTransactionWithPropagationNestedAndRollback(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingTransactionWithManualSavepointAndRollback() throws SQLException {
|
||||
doTestExistingTransactionWithPropagationNestedAndRollback(true);
|
||||
}
|
||||
|
||||
private void doTestExistingTransactionWithPropagationNestedAndRollback(final boolean manualSavepoint)
|
||||
throws SQLException {
|
||||
|
||||
final DataSource ds = mock(DataSource.class);
|
||||
JdoDialect dialect = mock(JdoDialect.class);
|
||||
final Connection con = mock(Connection.class);
|
||||
DatabaseMetaData md = mock(DatabaseMetaData.class);
|
||||
Savepoint sp = mock(Savepoint.class);
|
||||
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
given(md.supportsSavepoints()).willReturn(true);
|
||||
given(con.getMetaData()).willReturn(md);
|
||||
given(con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1)).willReturn(sp);
|
||||
final TransactionTemplate tt = new TransactionTemplate();
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
|
||||
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
|
||||
given(dialect.getJdbcConnection(pm, false)).willReturn(conHandle);
|
||||
given(tx.isActive()).willReturn(!manualSavepoint);
|
||||
|
||||
JdoTransactionManager tm = new JdoTransactionManager();
|
||||
tm.setNestedTransactionAllowed(true);
|
||||
tm.setPersistenceManagerFactory(pmf);
|
||||
tm.setDataSource(ds);
|
||||
tm.setJdoDialect(dialect);
|
||||
tt.setTransactionManager(tm);
|
||||
final List l = new ArrayList();
|
||||
l.add("test");
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
Object result = tt.execute(new TransactionCallback() {
|
||||
@Override
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
|
||||
if (manualSavepoint) {
|
||||
Object savepoint = status.createSavepoint();
|
||||
status.rollbackToSavepoint(savepoint);
|
||||
}
|
||||
else {
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
|
||||
status.setRollbackOnly();
|
||||
}
|
||||
});
|
||||
}
|
||||
PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true).flush();
|
||||
return l;
|
||||
}
|
||||
});
|
||||
assertTrue("Correct result list", result == l);
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(con).setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1);
|
||||
verify(con).rollback(sp);
|
||||
verify(dialect).beginTransaction(tx, tt);
|
||||
verify(dialect).releaseJdbcConnection(conHandle, pm);
|
||||
verify(dialect).cleanupTransaction(null);
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFlush() {
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
given(pm.currentTransaction()).willReturn(tx);
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
status.flush();
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
verify(pm).flush();
|
||||
verify(pm).close();
|
||||
verify(tx).begin();
|
||||
verify(tx).commit();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,159 +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.Map;
|
||||
import java.util.Properties;
|
||||
import javax.jdo.JDOFatalUserException;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class LocalPersistenceManagerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBean() throws IOException {
|
||||
final PersistenceManagerFactory pmf = mock(PersistenceManagerFactory.class);
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
|
||||
@Override
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
|
||||
return pmf;
|
||||
}
|
||||
};
|
||||
pmfb.setJdoProperties(new Properties());
|
||||
pmfb.afterPropertiesSet();
|
||||
assertSame(pmf, pmfb.getObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithInvalidSettings() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean();
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown JDOFatalUserException");
|
||||
}
|
||||
catch (JDOFatalUserException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithIncompleteProperties() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myKey", "myValue");
|
||||
pmfb.setJdoProperties(props);
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown JDOFatalUserException");
|
||||
}
|
||||
catch (JDOFatalUserException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithInvalidProperty() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
|
||||
@Override
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
|
||||
throw new IllegalArgumentException((String) props.get("myKey"));
|
||||
}
|
||||
};
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myKey", "myValue");
|
||||
pmfb.setJdoProperties(props);
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
assertTrue("Correct exception", "myValue".equals(ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithFile() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
|
||||
@Override
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
|
||||
throw new IllegalArgumentException((String) props.get("myKey"));
|
||||
}
|
||||
};
|
||||
pmfb.setConfigLocation(new ClassPathResource("test.properties", getClass()));
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
assertTrue("Correct exception", "myValue".equals(ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithName() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
|
||||
@Override
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
|
||||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
};
|
||||
pmfb.setPersistenceManagerFactoryName("myName");
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
assertTrue("Correct exception", "myName".equals(ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPersistenceManagerFactoryBeanWithNameAndProperties() throws IOException {
|
||||
LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
|
||||
@Override
|
||||
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
|
||||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
};
|
||||
pmfb.setPersistenceManagerFactoryName("myName");
|
||||
pmfb.getJdoPropertyMap().put("myKey", "myValue");
|
||||
try {
|
||||
pmfb.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("persistenceManagerFactoryName") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("jdoProp") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,148 +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.io.IOException;
|
||||
import javax.jdo.PersistenceManager;
|
||||
import javax.jdo.PersistenceManagerFactory;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockFilterConfig;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.mock.web.test.PassThroughFilterChain;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @since 15.06.2004
|
||||
*/
|
||||
public class OpenPersistenceManagerInViewTests {
|
||||
|
||||
@Test
|
||||
public void testOpenPersistenceManagerInViewInterceptor() throws Exception {
|
||||
PersistenceManagerFactory pmf = mock(PersistenceManagerFactory.class);
|
||||
PersistenceManager pm = mock(PersistenceManager.class);
|
||||
|
||||
OpenPersistenceManagerInViewInterceptor interceptor = new OpenPersistenceManagerInViewInterceptor();
|
||||
interceptor.setPersistenceManagerFactory(pmf);
|
||||
|
||||
MockServletContext sc = new MockServletContext();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(sc);
|
||||
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
interceptor.preHandle(new ServletWebRequest(request));
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
// check that further invocations simply participate
|
||||
interceptor.preHandle(new ServletWebRequest(request));
|
||||
|
||||
interceptor.preHandle(new ServletWebRequest(request));
|
||||
interceptor.postHandle(new ServletWebRequest(request), null);
|
||||
interceptor.afterCompletion(new ServletWebRequest(request), null);
|
||||
|
||||
interceptor.postHandle(new ServletWebRequest(request), null);
|
||||
interceptor.afterCompletion(new ServletWebRequest(request), null);
|
||||
|
||||
interceptor.preHandle(new ServletWebRequest(request));
|
||||
interceptor.postHandle(new ServletWebRequest(request), null);
|
||||
interceptor.afterCompletion(new ServletWebRequest(request), null);
|
||||
|
||||
interceptor.postHandle(new ServletWebRequest(request), null);
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(pmf));
|
||||
|
||||
interceptor.afterCompletion(new ServletWebRequest(request), null);
|
||||
assertFalse(TransactionSynchronizationManager.hasResource(pmf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenPersistenceManagerInViewFilter() throws Exception {
|
||||
final PersistenceManagerFactory pmf = mock(PersistenceManagerFactory.class);
|
||||
PersistenceManager pm = mock(PersistenceManager.class);
|
||||
|
||||
given(pmf.getPersistenceManager()).willReturn(pm);
|
||||
final PersistenceManagerFactory pmf2 = mock(PersistenceManagerFactory.class);
|
||||
PersistenceManager pm2 = mock(PersistenceManager.class);
|
||||
|
||||
given(pmf2.getPersistenceManager()).willReturn(pm2);
|
||||
|
||||
MockServletContext sc = new MockServletContext();
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(sc);
|
||||
wac.getDefaultListableBeanFactory().registerSingleton("persistenceManagerFactory", pmf);
|
||||
wac.getDefaultListableBeanFactory().registerSingleton("myPersistenceManagerFactory", pmf2);
|
||||
wac.refresh();
|
||||
sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(sc);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
|
||||
MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
|
||||
filterConfig2.addInitParameter("persistenceManagerFactoryBeanName", "myPersistenceManagerFactory");
|
||||
|
||||
final OpenPersistenceManagerInViewFilter filter = new OpenPersistenceManagerInViewFilter();
|
||||
filter.init(filterConfig);
|
||||
final OpenPersistenceManagerInViewFilter filter2 = new OpenPersistenceManagerInViewFilter();
|
||||
filter2.init(filterConfig2);
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(pmf));
|
||||
servletRequest.setAttribute("invoked", Boolean.TRUE);
|
||||
}
|
||||
};
|
||||
|
||||
final FilterChain filterChain2 = new FilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
|
||||
throws IOException, ServletException {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(pmf2));
|
||||
filter.doFilter(servletRequest, servletResponse, filterChain);
|
||||
}
|
||||
};
|
||||
|
||||
FilterChain filterChain3 = new PassThroughFilterChain(filter2, filterChain2);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertFalse(TransactionSynchronizationManager.hasResource(pmf2));
|
||||
filter2.doFilter(request, response, filterChain3);
|
||||
assertFalse(TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertFalse(TransactionSynchronizationManager.hasResource(pmf2));
|
||||
assertNotNull(request.getAttribute("invoked"));
|
||||
|
||||
verify(pm).close();
|
||||
verify(pm2).close();
|
||||
|
||||
wac.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
myKey=myValue
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,7 +20,7 @@ import org.springframework.dao.DataAccessException;
|
|||
|
||||
/**
|
||||
* Interface implemented by Spring integrations with data access technologies
|
||||
* that throw runtime exceptions, such as JPA, TopLink, JDO and Hibernate.
|
||||
* that throw runtime exceptions, such as JPA and Hibernate.
|
||||
*
|
||||
* <p>This allows consistent usage of combined exception translation functionality,
|
||||
* without forcing a single translator to understand every single possible type
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -83,8 +83,8 @@ public class LocalConnectionFactoryBean implements FactoryBean<Object>, Initiali
|
|||
* <p>The ManagerConnectionFactory will usually be set up as separate bean
|
||||
* (potentially as inner bean), populated with JavaBean properties:
|
||||
* a ManagerConnectionFactory is encouraged to follow the JavaBean pattern
|
||||
* by the JCA specification, analogous to a JDBC DataSource and a JDO
|
||||
* PersistenceManagerFactory.
|
||||
* by the JCA specification, analogous to a JDBC DataSource and a JPA
|
||||
* EntityManagerFactory.
|
||||
* <p>Note that the ManagerConnectionFactory implementation might expect
|
||||
* a reference to its JCA 1.5 ResourceAdapter, expressed through the
|
||||
* {@link javax.resource.spi.ResourceAdapterAssociation} interface.
|
||||
|
|
|
@ -1726,7 +1726,7 @@ proxies for beans containing that annotation:
|
|||
The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager`
|
||||
definition, which is not included in this generic file (although it could be) because it
|
||||
will be specific to the application's transaction requirements (typically JTA, as in
|
||||
this example, or Hibernate, JDO or JDBC):
|
||||
this example, or Hibernate or JDBC):
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
|
@ -1450,7 +1450,7 @@ proxies for beans containing that annotation:
|
|||
The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager`
|
||||
definition, which is not included in this generic file (although it could be) because it
|
||||
will be specific to the application's transaction requirements (typically JTA, as in
|
||||
this example, or Hibernate, JDO or JDBC):
|
||||
this example, or Hibernate or JDBC):
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
|
@ -29,8 +29,7 @@ Framework. The Spring Framework provides a consistent abstraction for transactio
|
|||
management that delivers the following benefits:
|
||||
|
||||
* Consistent programming model across different transaction APIs such as Java
|
||||
Transaction API (JTA), JDBC, Hibernate, Java Persistence API (JPA), and Java Data
|
||||
Objects (JDO).
|
||||
Transaction API (JTA), JDBC, Hibernate, and Java Persistence API (JPA).
|
||||
* Support for <<transaction-declarative,declarative transaction management>>.
|
||||
* Simpler API for <<transaction-programmatic,programmatic>> transaction management than
|
||||
complex transaction APIs such as JTA.
|
||||
|
@ -384,7 +383,7 @@ It should now be clear how you create different transaction managers, and how th
|
|||
linked to related resources that need to be synchronized to transactions (for example
|
||||
`DataSourceTransactionManager` to a JDBC `DataSource`, `HibernateTransactionManager` to
|
||||
a Hibernate `SessionFactory`, and so forth). This section describes how the application
|
||||
code, directly or indirectly using a persistence API such as JDBC, Hibernate, or JDO,
|
||||
code, directly or indirectly using a persistence API such as JDBC, Hibernate, or JPA,
|
||||
ensures that these resources are created, reused, and cleaned up properly. The section
|
||||
also discusses how transaction synchronization is triggered (optionally) through the
|
||||
relevant `PlatformTransactionManager`.
|
||||
|
@ -408,12 +407,11 @@ chapters of this reference documentation.
|
|||
[[tx-resource-synchronization-low]]
|
||||
==== Low-level synchronization approach
|
||||
Classes such as `DataSourceUtils` (for JDBC), `EntityManagerFactoryUtils` (for JPA),
|
||||
`SessionFactoryUtils` (for Hibernate), `PersistenceManagerFactoryUtils` (for JDO), and
|
||||
so on exist at a lower level. When you want the application code to deal directly with
|
||||
the resource types of the native persistence APIs, you use these classes to ensure that
|
||||
proper Spring Framework-managed instances are obtained, transactions are (optionally)
|
||||
synchronized, and exceptions that occur in the process are properly mapped to a
|
||||
consistent API.
|
||||
`SessionFactoryUtils` (for Hibernate), and so on exist at a lower level. When you want the
|
||||
application code to deal directly with the resource types of the native persistence APIs,
|
||||
you use these classes to ensure that proper Spring Framework-managed instances are obtained,
|
||||
transactions are (optionally) synchronized, and exceptions that occur in the process are
|
||||
properly mapped to a consistent API.
|
||||
|
||||
For example, in the case of JDBC, instead of the traditional JDBC approach of calling
|
||||
the `getConnection()` method on the `DataSource`, you instead use Spring's
|
||||
|
@ -485,7 +483,7 @@ necessary. The differences between the two types of transaction management are:
|
|||
|
||||
* Unlike EJB CMT, which is tied to JTA, the Spring Framework's declarative transaction
|
||||
management works in any environment. It can work with JTA transactions or local
|
||||
transactions using JDBC, JPA, Hibernate or JDO by simply adjusting the configuration
|
||||
transactions using JDBC, JPA or Hibernate by simply adjusting the configuration
|
||||
files.
|
||||
* You can apply the Spring Framework declarative transaction management to any class,
|
||||
not merely special classes such as EJBs.
|
||||
|
@ -2058,7 +2056,7 @@ For more information about the Spring Framework's transaction support:
|
|||
[[dao-introduction]]
|
||||
=== Introduction
|
||||
The Data Access Object (DAO) support in Spring is aimed at making it easy to work with
|
||||
data access technologies like JDBC, Hibernate, JPA or JDO in a consistent way. This
|
||||
data access technologies like JDBC, Hibernate or JPA in a consistent way. This
|
||||
allows one to switch between the aforementioned persistence technologies fairly easily
|
||||
and it also allows one to code without worrying about catching exceptions that are
|
||||
specific to each technology.
|
||||
|
@ -2074,8 +2072,8 @@ the root exception. These exceptions wrap the original exception so there is nev
|
|||
risk that one might lose any information as to what might have gone wrong.
|
||||
|
||||
In addition to JDBC exceptions, Spring can also wrap Hibernate-specific exceptions,
|
||||
converting them to a set of focused runtime exceptions (the same is true for JDO and
|
||||
JPA exceptions). This allows one to handle most persistence exceptions, which are
|
||||
converting them to a set of focused runtime exceptions (the same is true for JPA
|
||||
exceptions). This allows one to handle most persistence exceptions, which are
|
||||
non-recoverable, only in the appropriate layers, without having annoying boilerplate
|
||||
catch-and-throw blocks and exception declarations in one's DAOs. (One can still trap
|
||||
and handle exceptions anywhere one needs to though.) As mentioned above, JDBC
|
||||
|
@ -2085,12 +2083,12 @@ programming model.
|
|||
|
||||
The above holds true for the various template classes in Springs support for various ORM
|
||||
frameworks. If one uses the interceptor-based classes then the application must care
|
||||
about handling `HibernateExceptions` and `JDOExceptions` itself, preferably via
|
||||
about handling `HibernateExceptions` and `PersistenceExceptions` itself, preferably via
|
||||
delegating to `SessionFactoryUtils`' `convertHibernateAccessException(..)` or
|
||||
`convertJdoAccessException()` methods respectively. These methods convert the exceptions
|
||||
`convertJpaAccessException()` methods respectively. These methods convert the exceptions
|
||||
to ones that are compatible with the exceptions in the `org.springframework.dao`
|
||||
exception hierarchy. As `JDOExceptions` are unchecked, they can simply get thrown too,
|
||||
sacrificing generic DAO abstraction in terms of exceptions though.
|
||||
exception hierarchy. As `PersistenceExceptions` are unchecked, they can simply get
|
||||
thrown too, sacrificing generic DAO abstraction in terms of exceptions though.
|
||||
|
||||
The exception hierarchy that Spring provides can be seen below. (Please note that the
|
||||
class hierarchy detailed in the image shows only a subset of the entire
|
||||
|
@ -4952,17 +4950,17 @@ The second option can also be easy. Some suggestions on how to implement this in
|
|||
|
||||
[[orm-introduction]]
|
||||
=== Introduction to ORM with Spring
|
||||
The Spring Framework supports integration with Hibernate, Java Persistence API (JPA)
|
||||
and Java Data Objects (JDO) for resource management, data access object
|
||||
(DAO) implementations, and transaction strategies. For example, for Hibernate there is
|
||||
first-class support with several convenient IoC features that address many typical
|
||||
Hibernate integration issues. You can configure all of the supported features for O/R
|
||||
(object relational) mapping tools through Dependency Injection. They can participate in
|
||||
Spring's resource and transaction management, and they comply with Spring's generic
|
||||
transaction and DAO exception hierarchies. The recommended integration style is to code
|
||||
DAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Spring's DAO
|
||||
templates is no longer recommended; however, coverage of this style can be found in the
|
||||
<<classic-spring-orm>> in the appendices.
|
||||
The Spring Framework supports integration with the Java Persistence API (JPA) as well
|
||||
as native Hibernate for resource management, data access object (DAO) implementations,
|
||||
and transaction strategies. For example, for Hibernate there is first-class support with
|
||||
several convenient IoC features that address many typical Hibernate integration issues.
|
||||
You can configure all of the supported features for O/R (object relational) mapping
|
||||
tools through Dependency Injection. They can participate in Spring's resource and
|
||||
transaction management, and they comply with Spring's generic transaction and DAO
|
||||
exception hierarchies. The recommended integration style is to code DAOs against plain
|
||||
Hibernate or JPA APIs. The older style of using Spring's DAO templates is no longer
|
||||
recommended; however, coverage of this style can be found in the <<classic-spring-orm>>
|
||||
in the appendices.
|
||||
|
||||
Spring adds significant enhancements to the ORM layer of your choice when you create
|
||||
data access applications. You can leverage as much of the integration support as you
|
||||
|
@ -5061,26 +5059,25 @@ translation benefits.
|
|||
|
||||
When it comes to transaction management, the `JdbcTemplate` class hooks in to the Spring
|
||||
transaction support and supports both JTA and JDBC transactions, through respective
|
||||
Spring transaction managers. For the supported ORM technologies Spring offers Hibernate,
|
||||
JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well as
|
||||
JTA support. For details on transaction support, see the <<transaction>> chapter.
|
||||
Spring transaction managers. For the supported ORM technologies Spring offers Hibernate
|
||||
and JPA support through the Hibernate and JPA transaction managers as well as JTA support.
|
||||
For details on transaction support, see the <<transaction>> chapter.
|
||||
|
||||
|
||||
|
||||
[[orm-exception-translation]]
|
||||
==== Exception translation
|
||||
When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle the
|
||||
persistence technology's native exception classes. The DAO throws a subclass of a
|
||||
`HibernateException`, `PersistenceException` or `JDOException` depending on the
|
||||
technology. These exceptions are all run-time exceptions and do not have to be declared
|
||||
or caught. You may also have to deal with `IllegalArgumentException` and
|
||||
`IllegalStateException`. This means that callers can only treat exceptions as generally
|
||||
fatal, unless they want to depend on the persistence technology's own exception
|
||||
structure. Catching specific causes such as an optimistic locking failure is not
|
||||
possible without tying the caller to the implementation strategy. This trade off might
|
||||
be acceptable to applications that are strongly ORM-based and/or do not need any special
|
||||
exception treatment. However, Spring enables exception translation to be applied
|
||||
transparently through the `@Repository` annotation:
|
||||
When you use Hibernate or JPA in a DAO, you must decide how to handle the persistence
|
||||
technology's native exception classes. The DAO throws a subclass of a `HibernateException`
|
||||
or `PersistenceException` depending on the technology. These exceptions are all runtime
|
||||
exceptions and do not have to be declared or caught. You may also have to deal with
|
||||
`IllegalArgumentException` and `IllegalStateException`. This means that callers can only
|
||||
treat exceptions as generally fatal, unless they want to depend on the persistence
|
||||
technology's own exception structure. Catching specific causes such as an optimistic
|
||||
locking failure is not possible without tying the caller to the implementation strategy.
|
||||
This trade-off might be acceptable to applications that are strongly ORM-based and/or
|
||||
do not need any special exception treatment. However, Spring enables exception
|
||||
translation to be applied transparently through the `@Repository` annotation:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
@ -5718,305 +5715,12 @@ following events occur when a JTA transaction commits:
|
|||
|
||||
|
||||
|
||||
[[orm-jdo]]
|
||||
=== JDO
|
||||
Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following the
|
||||
same style as the Hibernate support. The corresponding integration classes reside in the
|
||||
`org.springframework.orm.jdo` package.
|
||||
|
||||
|
||||
|
||||
[[orm-jdo-setup]]
|
||||
==== PersistenceManagerFactory setup
|
||||
|
||||
Spring provides a `LocalPersistenceManagerFactoryBean` class that allows you to define a
|
||||
local JDO `PersistenceManagerFactory` within a Spring application context:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
|
||||
<property name="configLocation" value="classpath:kodo.properties"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
Alternatively, you can set up a `PersistenceManagerFactory` through direct instantiation
|
||||
of a `PersistenceManagerFactory` implementation class. A JDO `PersistenceManagerFactory`
|
||||
implementation class follows the JavaBeans pattern, just like a JDBC `DataSource`
|
||||
implementation class, which is a natural fit for a configuration that uses Spring. This
|
||||
setup style usually supports a Spring-defined JDBC `DataSource`, passed into the
|
||||
`connectionFactory` property. For example, for the open source JDO implementation
|
||||
DataNucleus (formerly JPOX) ( http://www.datanucleus.org/[http://www.datanucleus.org/]),
|
||||
this is the XML configuration of the `PersistenceManagerFactory` implementation:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||
<property name="driverClassName" value="${jdbc.driverClassName}"/>
|
||||
<property name="url" value="${jdbc.url}"/>
|
||||
<property name="username" value="${jdbc.username}"/>
|
||||
<property name="password" value="${jdbc.password}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close">
|
||||
<property name="connectionFactory" ref="dataSource"/>
|
||||
<property name="nontransactionalRead" value="true"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
You can also set up JDO `PersistenceManagerFactory` in the JNDI environment of a Java EE
|
||||
application server, usually through the JCA connector provided by the particular JDO
|
||||
implementation. Spring's standard `JndiObjectFactoryBean` or `<jee:jndi-lookup>` can be
|
||||
used to retrieve and expose such a `PersistenceManagerFactory`. However, outside an EJB
|
||||
context, no real benefit exists in holding the `PersistenceManagerFactory` in JNDI: only
|
||||
choose such a setup for a good reason. See <<orm-hibernate-resources>> for a discussion;
|
||||
the arguments there apply to JDO as well.
|
||||
|
||||
|
||||
|
||||
[[orm-jdo-daos-straight]]
|
||||
==== Implementing DAOs based on the plain JDO API
|
||||
DAOs can also be written directly against plain JDO API, without any Spring
|
||||
dependencies, by using an injected `PersistenceManagerFactory`. The following is an
|
||||
example of a corresponding DAO implementation:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
public class ProductDaoImpl implements ProductDao {
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
|
||||
this.persistenceManagerFactory = pmf;
|
||||
}
|
||||
|
||||
public Collection loadProductsByCategory(String category) {
|
||||
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
|
||||
try {
|
||||
Query query = pm.newQuery(Product.class, "category = pCategory");
|
||||
query.declareParameters("String pCategory");
|
||||
return query.execute(category);
|
||||
}
|
||||
finally {
|
||||
pm.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl">
|
||||
<property name="persistenceManagerFactory" ref="myPmf"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
The main problem with such DAOs is that they always get a new `PersistenceManager` from
|
||||
the factory. To access a Spring-managed transactional `PersistenceManager`, define a
|
||||
`TransactionAwarePersistenceManagerFactoryProxy` (as included in Spring) in front of
|
||||
your target `PersistenceManagerFactory`, then passing a reference to that proxy into
|
||||
your DAOs as in the following example:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="myPmfProxy"
|
||||
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
|
||||
<property name="targetPersistenceManagerFactory" ref="myPmf"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl">
|
||||
<property name="persistenceManagerFactory" ref="myPmfProxy"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
Your data access code will receive a transactional `PersistenceManager` (if any) from
|
||||
the `PersistenceManagerFactory.getPersistenceManager()` method that it calls. The latter
|
||||
method call goes through the proxy, which first checks for a current transactional
|
||||
`PersistenceManager` before getting a new one from the factory. Any `close()` calls on
|
||||
the `PersistenceManager` are ignored in case of a transactional `PersistenceManager`.
|
||||
|
||||
If your data access code always runs within an active transaction (or at least within
|
||||
active transaction synchronization), it is safe to omit the `PersistenceManager.close()`
|
||||
call and thus the entire `finally` block, which you might do to keep your DAO
|
||||
implementations concise:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
public class ProductDaoImpl implements ProductDao {
|
||||
|
||||
private PersistenceManagerFactory persistenceManagerFactory;
|
||||
|
||||
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
|
||||
this.persistenceManagerFactory = pmf;
|
||||
}
|
||||
|
||||
public Collection loadProductsByCategory(String category) {
|
||||
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
|
||||
Query query = pm.newQuery(Product.class, "category = pCategory");
|
||||
query.declareParameters("String pCategory");
|
||||
return query.execute(category);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
With such DAOs that rely on active transactions, it is recommended that you enforce
|
||||
active transactions through turning off
|
||||
`TransactionAwarePersistenceManagerFactoryProxy`'s `allowCreate` flag:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="myPmfProxy"
|
||||
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
|
||||
<property name="targetPersistenceManagerFactory" ref="myPmf"/>
|
||||
<property name="allowCreate" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl">
|
||||
<property name="persistenceManagerFactory" ref="myPmfProxy"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
The main advantage of this DAO style is that it depends on JDO API only; no import of
|
||||
any Spring class is required. This is of course appealing from a non-invasiveness
|
||||
perspective, and might feel more natural to JDO developers.
|
||||
|
||||
However, the DAO throws plain `JDOException` (which is unchecked, so does not have to be
|
||||
declared or caught), which means that callers can only treat exceptions as fatal, unless
|
||||
you want to depend on JDO's own exception structure. Catching specific causes such as an
|
||||
optimistic locking failure is not possible without tying the caller to the
|
||||
implementation strategy. This trade off might be acceptable to applications that are
|
||||
strongly JDO-based and/or do not need any special exception treatment.
|
||||
|
||||
In summary, you can DAOs based on the plain JDO API, and they can still participate in
|
||||
Spring-managed transactions. This strategy might appeal to you if you are already
|
||||
familiar with JDO. However, such DAOs throw plain `JDOException`, and you would have to
|
||||
convert explicitly to Spring's `DataAccessException` (if desired).
|
||||
|
||||
|
||||
|
||||
[[orm-jdo-tx]]
|
||||
==== Transaction management
|
||||
[NOTE]
|
||||
====
|
||||
You are __strongly__ encouraged to read <<transaction-declarative>> if you have not done
|
||||
so, to get a more detailed coverage of Spring's declarative transaction support.
|
||||
====
|
||||
|
||||
To execute service operations within transactions, you can use Spring's common
|
||||
declarative transaction facilities. For example:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
http://www.springframework.org/schema/aop
|
||||
http://www.springframework.org/schema/aop/spring-aop.xsd">
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">
|
||||
<property name="persistenceManagerFactory" ref="myPmf"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myProductService" class="product.ProductServiceImpl">
|
||||
<property name="productDao" ref="myProductDao"/>
|
||||
</bean>
|
||||
|
||||
<tx:advice id="txAdvice" transaction-manager="txManager">
|
||||
<tx:attributes>
|
||||
<tx:method name="increasePrice*" propagation="REQUIRED"/>
|
||||
<tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
|
||||
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="productServiceMethods"
|
||||
expression="execution(* product.ProductService.*(..))"/>
|
||||
<aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
|
||||
</aop:config>
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
JDO requires an active transaction to modify a persistent object. The non-transactional
|
||||
flush concept does not exist in JDO, in contrast to Hibernate. For this reason, you need
|
||||
to set up the chosen JDO implementation for a specific environment. Specifically, you
|
||||
need to set it up explicitly for JTA synchronization, to detect an active JTA
|
||||
transaction itself. This is not necessary for local transactions as performed by
|
||||
Spring's `JdoTransactionManager`, but it is necessary to participate in JTA
|
||||
transactions, whether driven by Spring's `JtaTransactionManager` or by EJB CMT and plain
|
||||
JTA.
|
||||
|
||||
`JdoTransactionManager` is capable of exposing a JDO transaction to JDBC access code
|
||||
that accesses the same JDBC `DataSource`, provided that the registered `JdoDialect`
|
||||
supports retrieval of the underlying JDBC `Connection`. This is the case for JDBC-based
|
||||
JDO 2.0 implementations by default.
|
||||
|
||||
|
||||
|
||||
[[orm-jdo-dialect]]
|
||||
==== JdoDialect
|
||||
|
||||
As an advanced feature, both `LocalPersistenceManagerFactoryBean` and `JdoTransactionManager`
|
||||
support a custom `JdoDialect` that can be passed into the `jdoDialect` bean property.
|
||||
Using a `JdoDialect` implementation, you can enable advanced features supported by Spring,
|
||||
usually in a vendor-specific manner:
|
||||
|
||||
* Applying specific transaction semantics such as custom isolation level or transaction
|
||||
timeout
|
||||
* Retrieving the transactional JDBC `Connection` for exposure to JDBC-based DAOs
|
||||
* Applying query timeouts, which are automatically calculated from Spring-managed
|
||||
transaction timeouts
|
||||
* Eagerly flushing a `PersistenceManager,` to make transactional changes visible to
|
||||
JDBC-based data access code
|
||||
* Advanced translation of `JDOExceptions` to Spring `DataAccessExceptions`
|
||||
|
||||
See the `JdoDialect` javadocs for more details on its operations and how to use them
|
||||
within Spring's JDO support.
|
||||
|
||||
|
||||
|
||||
|
||||
[[orm-jpa]]
|
||||
=== JPA
|
||||
The Spring JPA, available under the `org.springframework.orm.jpa` package, offers
|
||||
comprehensive support for the
|
||||
http://www.oracle.com/technetwork/articles/javaee/jpa-137156.html[Java Persistence
|
||||
API] in a similar manner to the integration with Hibernate or JDO, while being aware of
|
||||
API] in a similar manner to the integration with Hibernate, while being aware of
|
||||
the underlying implementation in order to provide additional features.
|
||||
|
||||
|
||||
|
@ -6472,7 +6176,7 @@ declarative transaction facilities. For example:
|
|||
Spring JPA allows a configured `JpaTransactionManager` to expose a JPA transaction to
|
||||
JDBC access code that accesses the same JDBC `DataSource`, provided that the registered
|
||||
`JpaDialect` supports retrieval of the underlying JDBC `Connection`. Out of the box,
|
||||
Spring provides dialects for the EclipseLink, Hibernate and OpenJPA JPA implementations.
|
||||
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
|
||||
See the next section for details on the `JpaDialect` mechanism.
|
||||
|
||||
|
||||
|
@ -7007,74 +6711,9 @@ Available attributes are:
|
|||
|
||||
|
||||
|
||||
[[oxm-xmlbeans]]
|
||||
=== XMLBeans
|
||||
XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML
|
||||
Infoset fidelity. It takes a different approach to that of most other O/X mapping
|
||||
frameworks, in that all classes that are generated from an XML Schema are all derived
|
||||
from `XmlObject`, and contain XML binding information in them.
|
||||
|
||||
For more information on XMLBeans, refer to the http://xmlbeans.apache.org/[__XMLBeans
|
||||
web site __]. The Spring-WS integration classes reside in the
|
||||
`org.springframework.oxm.xmlbeans` package.
|
||||
|
||||
|
||||
|
||||
[[oxm-xmlbeans-marshaller]]
|
||||
==== XmlBeansMarshaller
|
||||
The `XmlBeansMarshaller` implements both the `Marshaller` and `Unmarshaller` interfaces.
|
||||
It can be configured as follows:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<beans>
|
||||
|
||||
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
|
||||
...
|
||||
|
||||
</beans>
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Note that the `XmlBeansMarshaller` can only marshal objects of type `XmlObject`, and not
|
||||
every `java.lang.Object`.
|
||||
====
|
||||
|
||||
|
||||
[[oxm-xmlbeans-xsd]]
|
||||
===== XML Schema-based Configuration
|
||||
The `xmlbeans-marshaller` tag configures a
|
||||
`org.springframework.oxm.xmlbeans.XmlBeansMarshaller`. Here is an example:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<oxm:xmlbeans-marshaller id="marshaller"/>
|
||||
----
|
||||
|
||||
Available attributes are:
|
||||
|
||||
|===
|
||||
| Attribute| Description| Required
|
||||
|
||||
| `id`
|
||||
| the id of the marshaller
|
||||
| no
|
||||
|
||||
| `options`
|
||||
| the bean name of the XmlOptions that is to be used for this marshaller. Typically a
|
||||
`XmlOptionsFactoryBean` definition
|
||||
| no
|
||||
|===
|
||||
|
||||
|
||||
|
||||
|
||||
[[oxm-jibx]]
|
||||
=== JiBX
|
||||
The JiBX framework offers a solution similar to that which JDO provides for ORM: a
|
||||
The JiBX framework offers a solution similar to that which Hibernate provides for ORM: a
|
||||
binding definition defines the rules for how your Java objects are converted to or from
|
||||
XML. After preparing the binding and compiling the classes, a JiBX binding compiler
|
||||
enhances the class files, and adds code to handle converting instances of the classes
|
||||
|
|
Loading…
Reference in New Issue