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.jpa;
018:
019: import java.sql.SQLException;
020:
021: import javax.persistence.EntityManager;
022: import javax.persistence.EntityManagerFactory;
023: import javax.persistence.PersistenceException;
024:
025: import org.springframework.dao.support.PersistenceExceptionTranslator;
026: import org.springframework.jdbc.datasource.ConnectionHandle;
027: import org.springframework.transaction.TransactionDefinition;
028: import org.springframework.transaction.TransactionException;
029:
030: /**
031: * SPI strategy that encapsulates certain functionality that standard JPA 1.0
032: * does not offer, such as access to the underlying JDBC Connection. This
033: * strategy is mainly intended for standalone usage of a JPA provider; most
034: * of its functionality is not relevant when running with JTA transactions.
035: *
036: * <p>Also allows for the provision of value-added methods for portable yet
037: * more capable EntityManager and EntityManagerFactory subinterfaces offered
038: * by Spring.
039: *
040: * <p>In general, it is recommended to derive from DefaultJpaDialect instead of
041: * implementing this interface directly. This allows for inheriting common
042: * behavior (present and future) from DefaultJpaDialect, only overriding
043: * specific hooks to plug in concrete vendor-specific behavior.
044: *
045: * @author Juergen Hoeller
046: * @author Rod Johnson
047: * @since 2.0
048: * @see DefaultJpaDialect
049: * @see JpaAccessor#setJpaDialect
050: * @see JpaTransactionManager#setJpaDialect
051: * @see JpaVendorAdapter#getJpaDialect()
052: * @see AbstractEntityManagerFactoryBean#setJpaDialect
053: * @see AbstractEntityManagerFactoryBean#setJpaVendorAdapter
054: */
055: public interface JpaDialect extends PersistenceExceptionTranslator {
056:
057: //-----------------------------------------------------------------------------------
058: // Hooks for non-standard persistence operations (used by EntityManagerFactory beans)
059: //-----------------------------------------------------------------------------------
060:
061: /**
062: * Return whether the EntityManagerFactoryPlus(Operations) interface is
063: * supported by this provider.
064: * @see EntityManagerFactoryPlusOperations
065: * @see EntityManagerFactoryPlus
066: */
067: boolean supportsEntityManagerFactoryPlusOperations();
068:
069: /**
070: * Return whether the EntityManagerPlus(Operations) interface is
071: * supported by this provider.
072: * @see EntityManagerPlusOperations
073: * @see EntityManagerPlus
074: */
075: boolean supportsEntityManagerPlusOperations();
076:
077: /**
078: * Return an EntityManagerFactoryPlusOperations implementation for
079: * the given raw EntityManagerFactory. This operations object can be
080: * used to serve the additional operations behind a proxy that
081: * implements the EntityManagerFactoryPlus interface.
082: * @param rawEntityManager the raw provider-specific EntityManagerFactory
083: * @return the EntityManagerFactoryPlusOperations implementation
084: */
085: EntityManagerFactoryPlusOperations getEntityManagerFactoryPlusOperations(
086: EntityManagerFactory rawEntityManager);
087:
088: /**
089: * Return an EntityManagerPlusOperations implementation for
090: * the given raw EntityManager. This operations object can be
091: * used to serve the additional operations behind a proxy that
092: * implements the EntityManagerPlus interface.
093: * @param rawEntityManager the raw provider-specific EntityManagerFactory
094: * @return the EntityManagerFactoryPlusOperations implementation
095: */
096: EntityManagerPlusOperations getEntityManagerPlusOperations(
097: EntityManager rawEntityManager);
098:
099: //-------------------------------------------------------------------------
100: // Hooks for transaction management (used by JpaTransactionManager)
101: //-------------------------------------------------------------------------
102:
103: /**
104: * Begin the given JPA transaction, applying the semantics specified by the
105: * given Spring transaction definition (in particular, an isolation level
106: * and a timeout). Called by JpaTransactionManager on transaction begin.
107: * <p>An implementation can configure the JPA Transaction object and then
108: * invoke <code>begin</code>, or invoke a special begin method that takes,
109: * for example, an isolation level.
110: * <p>An implementation can apply the read-only flag as flush mode. In that case,
111: * a transaction data object can be returned that holds the previous flush mode
112: * (and possibly other data), to be reset in <code>cleanupTransaction</code>.
113: * It may also apply the read-only flag and isolation level to the underlying
114: * JDBC Connection before beginning the transaction.
115: * <p>Implementations can also use the Spring transaction name, as exposed by the
116: * passed-in TransactionDefinition, to optimize for specific data access use cases
117: * (effectively using the current transaction name as use case identifier).
118: * <p>This method also allows for exposing savepoint capabilities if supported by
119: * the persistence provider, through returning an Object that implements Spring's
120: * {@link org.springframework.transaction.SavepointManager} interface.
121: * {@link JpaTransactionManager} will use this capability if needed.
122: * @param entityManager the EntityManager to begin a JPA transaction on
123: * @param definition the Spring transaction definition that defines semantics
124: * @return an arbitrary object that holds transaction data, if any
125: * (to be passed into {@link #cleanupTransaction}). May implement the
126: * {@link org.springframework.transaction.SavepointManager} interface.
127: * @throws javax.persistence.PersistenceException if thrown by JPA methods
128: * @throws java.sql.SQLException if thrown by JDBC methods
129: * @throws org.springframework.transaction.TransactionException in case of invalid arguments
130: * @see #cleanupTransaction
131: * @see javax.persistence.EntityTransaction#begin
132: * @see org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction
133: */
134: Object beginTransaction(EntityManager entityManager,
135: TransactionDefinition definition)
136: throws PersistenceException, SQLException,
137: TransactionException;
138:
139: /**
140: * Prepare a JPA transaction, applying the specified semantics. Called by
141: * EntityManagerFactoryUtils when enlisting an EntityManager in a JTA transaction.
142: * <p>An implementation can apply the read-only flag as flush mode. In that case,
143: * a transaction data object can be returned that holds the previous flush mode
144: * (and possibly other data), to be reset in <code>cleanupTransaction</code>.
145: * <p>Implementations can also use the Spring transaction name, as exposed by the
146: * passed-in TransactionDefinition, to optimize for specific data access use cases
147: * (effectively using the current transaction name as use case identifier).
148: * @param entityManager the EntityManager to begin a JPA transaction on
149: * @param readOnly whether the transaction is supposed to be read-only
150: * @param name the name of the transaction (if any)
151: * @return an arbitrary object that holds transaction data, if any
152: * (to be passed into cleanupTransaction)
153: * @throws javax.persistence.PersistenceException if thrown by JPA methods
154: * @see #cleanupTransaction
155: */
156: Object prepareTransaction(EntityManager entityManager,
157: boolean readOnly, String name) throws PersistenceException;
158:
159: /**
160: * Clean up the transaction via the given transaction data. Called by
161: * JpaTransactionManager and EntityManagerFactoryUtils on transaction cleanup.
162: * <p>An implementation can, for example, reset read-only flag and
163: * isolation level of the underlying JDBC Connection. Furthermore,
164: * an exposed data access use case can be reset here.
165: * @param transactionData arbitrary object that holds transaction data, if any
166: * (as returned by beginTransaction or prepareTransaction)
167: * @see #beginTransaction
168: * @see org.springframework.jdbc.datasource.DataSourceUtils#resetConnectionAfterTransaction
169: */
170: void cleanupTransaction(Object transactionData);
171:
172: /**
173: * Retrieve the JDBC Connection that the given JPA EntityManager uses underneath,
174: * if accessing a relational database. This method will just get invoked if actually
175: * needing access to the underlying JDBC Connection, usually within an active JPA
176: * transaction (for example, by JpaTransactionManager). The returned handle will
177: * be passed into the <code>releaseJdbcConnection</code> method when not needed anymore.
178: * <p>This strategy is necessary as JPA 1.0 does not provide a standard way to retrieve
179: * the underlying JDBC Connection (due to the fact that a JPA implementation might not
180: * work with a relational database at all).
181: * <p>Implementations are encouraged to return an unwrapped Connection object, i.e.
182: * the Connection as they got it from the connection pool. This makes it easier for
183: * application code to get at the underlying native JDBC Connection, like an
184: * OracleConnection, which is sometimes necessary for LOB handling etc. We assume
185: * that calling code knows how to properly handle the returned Connection object.
186: * <p>In a simple case where the returned Connection will be auto-closed with the
187: * EntityManager or can be released via the Connection object itself, an
188: * implementation can return a SimpleConnectionHandle that just contains the
189: * Connection. If some other object is needed in <code>releaseJdbcConnection</code>,
190: * an implementation should use a special handle that references that other object.
191: * @param entityManager the current JPA EntityManager
192: * @param readOnly whether the Connection is only needed for read-only purposes
193: * @return a handle for the JDBC Connection, to be passed into
194: * <code>releaseJdbcConnection</code>, or <code>null</code>
195: * if no JDBC Connection can be retrieved
196: * @throws javax.persistence.PersistenceException if thrown by JPA methods
197: * @throws java.sql.SQLException if thrown by JDBC methods
198: * @see #releaseJdbcConnection
199: * @see org.springframework.jdbc.datasource.ConnectionHandle#getConnection
200: * @see org.springframework.jdbc.datasource.SimpleConnectionHandle
201: * @see JpaTransactionManager#setDataSource
202: * @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
203: */
204: ConnectionHandle getJdbcConnection(EntityManager entityManager,
205: boolean readOnly) throws PersistenceException, SQLException;
206:
207: /**
208: * Release the given JDBC Connection, which has originally been retrieved
209: * via <code>getJdbcConnection</code>. This should be invoked in any case,
210: * to allow for proper release of the retrieved Connection handle.
211: * <p>An implementation might simply do nothing, if the Connection returned
212: * by <code>getJdbcConnection</code> will be implicitly closed when the JPA
213: * transaction completes or when the EntityManager is closed.
214: * @param conHandle the JDBC Connection handle to release
215: * @param entityManager the current JPA EntityManager
216: * @throws javax.persistence.PersistenceException if thrown by JPA methods
217: * @throws java.sql.SQLException if thrown by JDBC methods
218: * @see #getJdbcConnection
219: */
220: void releaseJdbcConnection(ConnectionHandle conHandle,
221: EntityManager entityManager) throws PersistenceException,
222: SQLException;
223:
224: }
|