001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.orm.jdo;
018:
019: import java.sql.SQLException;
020:
021: import javax.jdo.JDOException;
022: import javax.jdo.PersistenceManager;
023: import javax.jdo.Query;
024: import javax.jdo.Transaction;
025:
026: import org.springframework.dao.DataAccessException;
027: import org.springframework.jdbc.datasource.ConnectionHandle;
028: import org.springframework.transaction.TransactionDefinition;
029: import org.springframework.transaction.TransactionException;
030:
031: /**
032: * SPI strategy that allows for customizing integration with a specific JDO provider,
033: * in particular regarding transaction management and exception translation. To be
034: * implemented for specific JDO providers such as JPOX, Kodo, Lido, Versant Open Access.
035: *
036: * <p>JDO 2.0 defines standard ways for most of the functionality covered here.
037: * Hence, Spring's {@link DefaultJdoDialect} uses the corresponding JDO 2.0 methods
038: * by default, to be overridden in a vendor-specific fashion if necessary.
039: * Vendor-specific subclasses of {@link DefaultJdoDialect} are still required for special
040: * transaction semantics and more sophisticated exception translation (if needed).
041: *
042: * <p>In general, it is recommended to derive from {@link DefaultJdoDialect} instead
043: * of implementing this interface directly. This allows for inheriting common
044: * behavior (present and future) from {@link DefaultJdoDialect}, only overriding
045: * specific hooks to plug in concrete vendor-specific behavior.
046: *
047: * @author Juergen Hoeller
048: * @since 02.11.2003
049: * @see JdoTransactionManager#setJdoDialect
050: * @see JdoAccessor#setJdoDialect
051: * @see DefaultJdoDialect
052: */
053: public interface JdoDialect {
054:
055: //-------------------------------------------------------------------------
056: // Hooks for transaction management (used by JdoTransactionManager)
057: //-------------------------------------------------------------------------
058:
059: /**
060: * Begin the given JDO transaction, applying the semantics specified by the
061: * given Spring transaction definition (in particular, an isolation level
062: * and a timeout). Invoked by JdoTransactionManager on transaction begin.
063: * <p>An implementation can configure the JDO Transaction object and then
064: * invoke <code>begin</code>, or invoke a special begin method that takes,
065: * for example, an isolation level.
066: * <p>An implementation can also apply read-only flag and isolation level to the
067: * underlying JDBC Connection before beginning the transaction. In that case,
068: * a transaction data object can be returned that holds the previous isolation
069: * level (and possibly other data), to be reset in <code>cleanupTransaction</code>.
070: * <p>Implementations can also use the Spring transaction name, as exposed by the
071: * passed-in TransactionDefinition, to optimize for specific data access use cases
072: * (effectively using the current transaction name as use case identifier).
073: * @param transaction the JDO transaction to begin
074: * @param definition the Spring transaction definition that defines semantics
075: * @return an arbitrary object that holds transaction data, if any
076: * (to be passed into cleanupTransaction)
077: * @throws JDOException if thrown by JDO methods
078: * @throws SQLException if thrown by JDBC methods
079: * @throws TransactionException in case of invalid arguments
080: * @see #cleanupTransaction
081: * @see javax.jdo.Transaction#begin
082: * @see org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction
083: */
084: Object beginTransaction(Transaction transaction,
085: TransactionDefinition definition) throws JDOException,
086: SQLException, TransactionException;
087:
088: /**
089: * Clean up the transaction via the given transaction data.
090: * Invoked by JdoTransactionManager on transaction cleanup.
091: * <p>An implementation can, for example, reset read-only flag and
092: * isolation level of the underlying JDBC Connection. Furthermore,
093: * an exposed data access use case can be reset here.
094: * @param transactionData arbitrary object that holds transaction data, if any
095: * (as returned by beginTransaction)
096: * @see #beginTransaction
097: * @see org.springframework.jdbc.datasource.DataSourceUtils#resetConnectionAfterTransaction
098: */
099: void cleanupTransaction(Object transactionData);
100:
101: /**
102: * Retrieve the JDBC Connection that the given JDO PersistenceManager uses underneath,
103: * if accessing a relational database. This method will just get invoked if actually
104: * needing access to the underlying JDBC Connection, usually within an active JDO
105: * transaction (for example, by JdoTransactionManager). The returned handle will
106: * be passed into the <code>releaseJdbcConnection</code> method when not needed anymore.
107: * <p>Implementations are encouraged to return an unwrapped Connection object, i.e.
108: * the Connection as they got it from the connection pool. This makes it easier for
109: * application code to get at the underlying native JDBC Connection, like an
110: * OracleConnection, which is sometimes necessary for LOB handling etc. We assume
111: * that calling code knows how to properly handle the returned Connection object.
112: * <p>In a simple case where the returned Connection will be auto-closed with the
113: * PersistenceManager or can be released via the Connection object itself, an
114: * implementation can return a SimpleConnectionHandle that just contains the
115: * Connection. If some other object is needed in <code>releaseJdbcConnection</code>,
116: * an implementation should use a special handle that references that other object.
117: * @param pm the current JDO PersistenceManager
118: * @param readOnly whether the Connection is only needed for read-only purposes
119: * @return a handle for the JDBC Connection, to be passed into
120: * <code>releaseJdbcConnection</code>, or <code>null</code>
121: * if no JDBC Connection can be retrieved
122: * @throws JDOException if thrown by JDO methods
123: * @throws SQLException if thrown by JDBC methods
124: * @see #releaseJdbcConnection
125: * @see org.springframework.jdbc.datasource.ConnectionHandle#getConnection
126: * @see org.springframework.jdbc.datasource.SimpleConnectionHandle
127: * @see JdoTransactionManager#setDataSource
128: * @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
129: */
130: ConnectionHandle getJdbcConnection(PersistenceManager pm,
131: boolean readOnly) throws JDOException, SQLException;
132:
133: /**
134: * Release the given JDBC Connection, which has originally been retrieved
135: * via <code>getJdbcConnection</code>. This should be invoked in any case,
136: * to allow for proper release of the retrieved Connection handle.
137: * <p>An implementation might simply do nothing, if the Connection returned
138: * by <code>getJdbcConnection</code> will be implicitly closed when the JDO
139: * transaction completes or when the PersistenceManager is closed.
140: * @param conHandle the JDBC Connection handle to release
141: * @param pm the current JDO PersistenceManager
142: * @throws JDOException if thrown by JDO methods
143: * @throws SQLException if thrown by JDBC methods
144: * @see #getJdbcConnection
145: */
146: void releaseJdbcConnection(ConnectionHandle conHandle,
147: PersistenceManager pm) throws JDOException, SQLException;
148:
149: /**
150: * Flush the given PersistenceManager, i.e. flush all changes (that have been
151: * applied to persistent objects) to the underlying database. This method will
152: * just get invoked when eager flushing is actually necessary, for example when
153: * JDBC access code needs to see changes within the same transaction.
154: * @param pm the current JDO PersistenceManager
155: * @throws JDOException in case of errors
156: * @see JdoAccessor#setFlushEager
157: */
158: void flush(PersistenceManager pm) throws JDOException;
159:
160: /**
161: * Apply the given timeout to the given JDO query object.
162: * <p>Invoked with the remaining time of a specified transaction timeout, if any.
163: * @param query the JDO query object to apply the timeout to
164: * @param timeout the timeout value to apply
165: * @throws JDOException if thrown by JDO methods
166: * @see JdoTemplate#prepareQuery
167: */
168: void applyQueryTimeout(Query query, int timeout)
169: throws JDOException;
170:
171: //-----------------------------------------------------------------------------------
172: // Hook for exception translation (used by JdoTransactionManager and JdoTemplate)
173: //-----------------------------------------------------------------------------------
174:
175: /**
176: * Translate the given JDOException to a corresponding exception from Spring's
177: * generic DataAccessException hierarchy. An implementation should apply
178: * PersistenceManagerFactoryUtils' standard exception translation if can't do
179: * anything more specific.
180: * <p>Of particular importance is the correct translation to
181: * DataIntegrityViolationException, for example on constraint violation.
182: * Unfortunately, standard JDO does not allow for portable detection of this.
183: * <p>Can use a SQLExceptionTranslator for translating underlying SQLExceptions
184: * in a database-specific fashion.
185: * @param ex the JDOException thrown
186: * @return the corresponding DataAccessException (must not be <code>null</code>)
187: * @see JdoAccessor#convertJdoAccessException
188: * @see JdoTransactionManager#convertJdoAccessException
189: * @see PersistenceManagerFactoryUtils#convertJdoAccessException
190: * @see org.springframework.dao.DataIntegrityViolationException
191: * @see org.springframework.jdbc.support.SQLExceptionTranslator
192: */
193: DataAccessException translateException(JDOException ex);
194:
195: }
|