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). Invoked 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 also apply read-only flag and isolation level to the
111: * underlying JDBC Connection before beginning the transaction. In that case,
112: * a transaction data object can be returned that holds the previous isolation
113: * level (and possibly other data), to be reset in <code>cleanupTransaction</code>.
114: * <p>Implementations can also use the Spring transaction name, as exposed by the
115: * passed-in TransactionDefinition, to optimize for specific data access use cases
116: * (effectively using the current transaction name as use case identifier).
117: * @param entityManager the EntityManager to begin a JPA transaction on
118: * @param definition the Spring transaction definition that defines semantics
119: * @return an arbitrary object that holds transaction data, if any
120: * (to be passed into cleanupTransaction)
121: * @throws javax.persistence.PersistenceException if thrown by JPA methods
122: * @throws java.sql.SQLException if thrown by JDBC methods
123: * @throws org.springframework.transaction.TransactionException in case of invalid arguments
124: * @see #cleanupTransaction
125: * @see javax.persistence.EntityTransaction#begin
126: * @see org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction
127: */
128: Object beginTransaction(EntityManager entityManager,
129: TransactionDefinition definition)
130: throws PersistenceException, SQLException,
131: TransactionException;
132:
133: /**
134: * Clean up the transaction via the given transaction data.
135: * Invoked by JpaTransactionManager on transaction cleanup.
136: * <p>An implementation can, for example, reset read-only flag and
137: * isolation level of the underlying JDBC Connection. Furthermore,
138: * an exposed data access use case can be reset here.
139: * @param transactionData arbitrary object that holds transaction data, if any
140: * (as returned by beginTransaction)
141: * @see #beginTransaction
142: * @see org.springframework.jdbc.datasource.DataSourceUtils#resetConnectionAfterTransaction
143: */
144: void cleanupTransaction(Object transactionData);
145:
146: /**
147: * Retrieve the JDBC Connection that the given JPA EntityManager uses underneath,
148: * if accessing a relational database. This method will just get invoked if actually
149: * needing access to the underlying JDBC Connection, usually within an active JPA
150: * transaction (for example, by JpaTransactionManager). The returned handle will
151: * be passed into the <code>releaseJdbcConnection</code> method when not needed anymore.
152: * <p>This strategy is necessary as JPA 1.0 does not provide a standard way to retrieve
153: * the underlying JDBC Connection (due to the fact that a JPA implementation might not
154: * work with a relational database at all).
155: * <p>Implementations are encouraged to return an unwrapped Connection object, i.e.
156: * the Connection as they got it from the connection pool. This makes it easier for
157: * application code to get at the underlying native JDBC Connection, like an
158: * OracleConnection, which is sometimes necessary for LOB handling etc. We assume
159: * that calling code knows how to properly handle the returned Connection object.
160: * <p>In a simple case where the returned Connection will be auto-closed with the
161: * EntityManager or can be released via the Connection object itself, an
162: * implementation can return a SimpleConnectionHandle that just contains the
163: * Connection. If some other object is needed in <code>releaseJdbcConnection</code>,
164: * an implementation should use a special handle that references that other object.
165: * @param entityManager the current JPA EntityManager
166: * @param readOnly whether the Connection is only needed for read-only purposes
167: * @return a handle for the JDBC Connection, to be passed into
168: * <code>releaseJdbcConnection</code>, or <code>null</code>
169: * if no JDBC Connection can be retrieved
170: * @throws javax.persistence.PersistenceException if thrown by JPA methods
171: * @throws java.sql.SQLException if thrown by JDBC methods
172: * @see #releaseJdbcConnection
173: * @see org.springframework.jdbc.datasource.ConnectionHandle#getConnection
174: * @see org.springframework.jdbc.datasource.SimpleConnectionHandle
175: * @see JpaTransactionManager#setDataSource
176: * @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
177: */
178: ConnectionHandle getJdbcConnection(EntityManager entityManager,
179: boolean readOnly) throws PersistenceException, SQLException;
180:
181: /**
182: * Release the given JDBC Connection, which has originally been retrieved
183: * via <code>getJdbcConnection</code>. This should be invoked in any case,
184: * to allow for proper release of the retrieved Connection handle.
185: * <p>An implementation might simply do nothing, if the Connection returned
186: * by <code>getJdbcConnection</code> will be implicitly closed when the JPA
187: * transaction completes or when the EntityManager is closed.
188: * @param conHandle the JDBC Connection handle to release
189: * @param entityManager the current JPA EntityManager
190: * @throws javax.persistence.PersistenceException if thrown by JPA methods
191: * @throws java.sql.SQLException if thrown by JDBC methods
192: * @see #getJdbcConnection
193: */
194: void releaseJdbcConnection(ConnectionHandle conHandle,
195: EntityManager entityManager) throws PersistenceException,
196: SQLException;
197:
198: }
|