Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@214 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
27 changed files with 0 additions and 4530 deletions
@ -1,221 +0,0 @@
@@ -1,221 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2008 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.toplink; |
||||
|
||||
import java.lang.reflect.InvocationHandler; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Proxy; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.sessions.UnitOfWork; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Abstract SessionFactory implementation that creates proxies for |
||||
* "managed" client Sessions and transaction-aware Session references. |
||||
* |
||||
* <p>Delegates to two template methods: |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2.6 |
||||
* @see #getMasterSession() |
||||
* @see #createClientSession() |
||||
*/ |
||||
public abstract class AbstractSessionFactory implements SessionFactory { |
||||
|
||||
/** Logger available to subclasses */ |
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
|
||||
/** |
||||
* Create a plain client Session for this factory's master Session. |
||||
* @see #createClientSession() |
||||
*/ |
||||
public Session createSession() throws TopLinkException { |
||||
logger.debug("Creating TopLink client Session"); |
||||
return createClientSession(); |
||||
} |
||||
|
||||
/** |
||||
* Create a "managed" client Session reference for an underlying |
||||
* client Session created for this factory. |
||||
* @see #createClientSession() |
||||
*/ |
||||
public Session createManagedClientSession() throws TopLinkException { |
||||
logger.debug("Creating managed TopLink client Session"); |
||||
Session target = createClientSession(); |
||||
return (Session) Proxy.newProxyInstance(target.getClass().getClassLoader(), |
||||
new Class[] {Session.class}, new ManagedClientInvocationHandler(target)); |
||||
} |
||||
|
||||
/** |
||||
* Create a transaction-aware Session reference for this factory's master Session, |
||||
* expecting transactions to be registered for this SessionFactory. |
||||
* @see #getMasterSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
public Session createTransactionAwareSession() throws TopLinkException { |
||||
logger.debug("Creating transaction-aware TopLink Session"); |
||||
return createTransactionAwareSession(this); |
||||
} |
||||
|
||||
/** |
||||
* Create a transaction-aware Session reference for this factory's master Session, |
||||
* expecting transactions to be registered for the given SessionFactory. |
||||
* <p>This method is public to allow custom SessionFactory facades to access |
||||
* it directly, if necessary. |
||||
* @param sessionFactory the SessionFactory that transactions |
||||
* are expected to be registered for |
||||
* @see #getMasterSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
public Session createTransactionAwareSession(SessionFactory sessionFactory) throws TopLinkException { |
||||
Session target = getMasterSession(); |
||||
return (Session) Proxy.newProxyInstance( |
||||
target.getClass().getClassLoader(), new Class[] {Session.class}, |
||||
new TransactionAwareInvocationHandler(sessionFactory, target)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return this factory's "master" Session. |
||||
* For example, a TopLink ServerSession. |
||||
* <p>Used for creating transaction-aware Session reference. |
||||
*/ |
||||
protected abstract Session getMasterSession(); |
||||
|
||||
/** |
||||
* Create a new client Session for this factory's master Session. |
||||
* For example, a TopLink ClientSession. |
||||
* <p>Used for creating plain Sessions and "managed" client Sessions. |
||||
* @throws TopLinkException if creation of a client Session failed |
||||
*/ |
||||
protected abstract Session createClientSession() throws TopLinkException; |
||||
|
||||
|
||||
/** |
||||
* Invocation handler that decorates a client Session with an "active" |
||||
* UnitOfWork. For use in situations where Spring's TopLinkTransactionManager |
||||
* requires a "managed" thread-safe TopLink Session. |
||||
*/ |
||||
private static class ManagedClientInvocationHandler implements InvocationHandler { |
||||
|
||||
private final Session target; |
||||
|
||||
private final UnitOfWork uow; |
||||
|
||||
public ManagedClientInvocationHandler(Session target) { |
||||
this.target = target; |
||||
this.uow = this.target.acquireUnitOfWork(); |
||||
} |
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
||||
// Invocation on Session interface coming in...
|
||||
|
||||
if (method.getName().equals("equals")) { |
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); |
||||
} |
||||
else if (method.getName().equals("hashCode")) { |
||||
// Use hashCode of SessionFactory proxy.
|
||||
return new Integer(System.identityHashCode(proxy)); |
||||
} |
||||
else if (method.getName().equals("getActiveSession")) { |
||||
return this.target; |
||||
} |
||||
else if (method.getName().equals("getActiveUnitOfWork")) { |
||||
return this.uow; |
||||
} |
||||
else if (method.getName().equals("release")) { |
||||
this.uow.release(); |
||||
this.target.release(); |
||||
} |
||||
|
||||
// Invoke method on target Session.
|
||||
try { |
||||
return method.invoke(this.target, args); |
||||
} |
||||
catch (InvocationTargetException ex) { |
||||
throw ex.getTargetException(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Invocation handler that delegates <code>getActiveSession</code> calls |
||||
* to SessionFactoryUtils, for being aware of thread-bound transactions. |
||||
*/ |
||||
private static class TransactionAwareInvocationHandler implements InvocationHandler { |
||||
|
||||
private final SessionFactory sessionFactory; |
||||
|
||||
private final Session target; |
||||
|
||||
public TransactionAwareInvocationHandler(SessionFactory sessionFactory, Session target) { |
||||
this.sessionFactory = sessionFactory; |
||||
this.target = target; |
||||
} |
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
||||
// Invocation on Session interface coming in...
|
||||
|
||||
if (method.getName().equals("equals")) { |
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); |
||||
} |
||||
else if (method.getName().equals("hashCode")) { |
||||
// Use hashCode of SessionFactory proxy.
|
||||
return new Integer(System.identityHashCode(proxy)); |
||||
} |
||||
else if (method.getName().equals("getActiveSession")) { |
||||
// Handle getActiveSession method: return transactional Session, if any.
|
||||
try { |
||||
return SessionFactoryUtils.doGetSession(this.sessionFactory, false); |
||||
} |
||||
catch (IllegalStateException ex) { |
||||
// getActiveSession is supposed to return the Session itself if no active one found.
|
||||
return this.target; |
||||
} |
||||
} |
||||
else if (method.getName().equals("getActiveUnitOfWork")) { |
||||
// Handle getActiveUnitOfWork method: return transactional UnitOfWork, if any.
|
||||
try { |
||||
return SessionFactoryUtils.doGetSession(this.sessionFactory, false).getActiveUnitOfWork(); |
||||
} |
||||
catch (IllegalStateException ex) { |
||||
// getActiveUnitOfWork is supposed to return null if no active one found.
|
||||
return null; |
||||
} |
||||
} |
||||
|
||||
// Invoke method on target Session.
|
||||
try { |
||||
return method.invoke(this.target, args); |
||||
} |
||||
catch (InvocationTargetException ex) { |
||||
throw ex.getTargetException(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,458 +0,0 @@
@@ -1,458 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2008 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.toplink; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
import java.lang.reflect.Method; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Properties; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.internal.databaseaccess.DatabasePlatform; |
||||
import oracle.toplink.jndi.JNDIConnector; |
||||
import oracle.toplink.sessionbroker.SessionBroker; |
||||
import oracle.toplink.sessions.DatabaseLogin; |
||||
import oracle.toplink.sessions.DatabaseSession; |
||||
import oracle.toplink.sessions.SessionLog; |
||||
import oracle.toplink.threetier.ServerSession; |
||||
import oracle.toplink.tools.sessionconfiguration.XMLLoader; |
||||
import oracle.toplink.tools.sessionmanagement.SessionManager; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.beans.PropertyAccessorFactory; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.CollectionUtils; |
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
/** |
||||
* Convenient JavaBean-style factory for a TopLink SessionFactory instance. |
||||
* Loads a TopLink <code>sessions.xml</code> file from the class path, exposing a |
||||
* specific TopLink Session defined there (usually a ServerSession). |
||||
* |
||||
* <p>TopLink Session configuration is done using a <code>sessions.xml</code> file. |
||||
* The most convenient way to create the <code>sessions.xml</code> file is to use |
||||
* the Oracle TopLink SessionsEditor workbench. The <code>sessions.xml</code> file |
||||
* contains all runtime configuration and points to a second XML or Class resource |
||||
* from which to load the actual TopLink project metadata (which defines mappings). |
||||
* |
||||
* <p>LocalSessionFactory loads the <code>sessions.xml</code> file during |
||||
* initialization in order to bootstrap the specified TopLink (Server)Session. |
||||
* The name of the actual config resource and the name of the Session to be loaded, |
||||
* if different from <code>sessions.xml</code> and "Session", respectively, can be |
||||
* configured through bean properties. |
||||
* |
||||
* <p>All resources (<code>sessions.xml</code> and Mapping Workbench metadata) are |
||||
* loaded using <code>ClassLoader.getResourceAsStream</code> calls by TopLink, so |
||||
* users may need to configure a ClassLoader with appropriate visibility. This is |
||||
* particularly important in J2EE environments where the TopLink metadata might be |
||||
* deployed to a different location than the Spring configuration. The ClassLoader |
||||
* used to search for the TopLink metadata and to load the persistent classes |
||||
* defined there will default to the the context ClassLoader for the current Thread. |
||||
* |
||||
* <p>TopLink's debug logging can be redirected to Commons Logging by passing a |
||||
* CommonsLoggingSessionLog to the "sessionLog" bean property. Otherwise, TopLink |
||||
* uses it's own DefaultSessionLog, whose levels are configured in the |
||||
* <code>sessions.xml</code> file. |
||||
* |
||||
* <p>This class has been tested against both TopLink 9.0.4 and TopLink 10.1.3. |
||||
* It will automatically adapt to the TopLink version encountered: for example, |
||||
* using an XMLSessionConfigLoader on 10.1.3, but an XMLLoader on 9.0.4. |
||||
* |
||||
* <p><b>NOTE:</b> When defining a TopLink SessionFactory in a Spring application |
||||
* context, you will usually define a bean of type <b>LocalSessionFactoryBean</b>. |
||||
* LocalSessionFactoryBean is a subclass of this factory, which will automatically |
||||
* expose the created TopLink SessionFactory instance as bean reference. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a> |
||||
* @since 1.2 |
||||
* @see LocalSessionFactoryBean |
||||
* @see TopLinkTemplate#setSessionFactory |
||||
* @see TopLinkTransactionManager#setSessionFactory |
||||
* @see SingleSessionFactory |
||||
* @see ServerSessionFactory |
||||
* @see oracle.toplink.threetier.ServerSession |
||||
* @see oracle.toplink.tools.sessionconfiguration.XMLLoader |
||||
* @see oracle.toplink.tools.sessionconfiguration.XMLSessionConfigLoader |
||||
*/ |
||||
public class LocalSessionFactory { |
||||
|
||||
/** |
||||
* The default location of the <code>sessions.xml</code> TopLink configuration file: |
||||
* "sessions.xml" in the class path. |
||||
*/ |
||||
public static final String DEFAULT_SESSIONS_XML = "sessions.xml"; |
||||
|
||||
/** |
||||
* The default session name to look for in the sessions.xml: "Session". |
||||
*/ |
||||
public static final String DEFAULT_SESSION_NAME = "Session"; |
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
/** |
||||
* The classpath location of the sessions TopLink configuration file. |
||||
*/ |
||||
private String configLocation = DEFAULT_SESSIONS_XML; |
||||
|
||||
/** |
||||
* The session name to look for in the sessions.xml configuration file. |
||||
*/ |
||||
private String sessionName = DEFAULT_SESSION_NAME; |
||||
|
||||
/** |
||||
* The ClassLoader to use to load the sessions.xml and project XML files. |
||||
*/ |
||||
private ClassLoader sessionClassLoader; |
||||
|
||||
private DatabaseLogin databaseLogin; |
||||
|
||||
private final Map loginPropertyMap = new HashMap(); |
||||
|
||||
private DataSource dataSource; |
||||
|
||||
private DatabasePlatform databasePlatform; |
||||
|
||||
private SessionLog sessionLog; |
||||
|
||||
|
||||
/** |
||||
* Set the TopLink <code>sessions.xml</code> configuration file that defines |
||||
* TopLink Sessions, as class path resource location. |
||||
* <p>The <code>sessions.xml</code> file will usually be placed in the META-INF |
||||
* directory or root path of a JAR file, or the <code>WEB-INF/classes</code> |
||||
* directory of a WAR file (specifying "META-INF/toplink-sessions.xml" or |
||||
* simply "toplink-sessions.xml" as config location, respectively). |
||||
* <p>The default config location is "sessions.xml" in the root of the class path. |
||||
* @param configLocation the class path location of the <code>sessions.xml</code> file |
||||
*/ |
||||
public void setConfigLocation(String configLocation) { |
||||
this.configLocation = configLocation; |
||||
} |
||||
|
||||
/** |
||||
* Set the name of the TopLink Session, as defined in TopLink's |
||||
* <code>sessions.xml</code> configuration file. |
||||
* The default session name is "Session". |
||||
*/ |
||||
public void setSessionName(String sessionName) { |
||||
this.sessionName = sessionName; |
||||
} |
||||
|
||||
/** |
||||
* Set the ClassLoader that should be used to lookup the config resources. |
||||
* If nothing is set here, then we will try to use the Thread context ClassLoader |
||||
* and the ClassLoader that loaded this factory class, in that order. |
||||
* <p>This ClassLoader will be used to load the TopLink configuration files |
||||
* and the project metadata. Furthermore, the TopLink ConversionManager will |
||||
* use this ClassLoader to load all TopLink entity classes. If the latter is not |
||||
* appropriate, users can configure a pre-login SessionEvent to alter the |
||||
* ConversionManager ClassLoader that TopLink will use at runtime. |
||||
*/ |
||||
public void setSessionClassLoader(ClassLoader sessionClassLoader) { |
||||
this.sessionClassLoader = sessionClassLoader; |
||||
} |
||||
|
||||
/** |
||||
* Specify the DatabaseLogin instance that carries the TopLink database |
||||
* configuration to use. This is an alternative to specifying that information |
||||
* in a <login> tag in the <code>sessions.xml</code> configuration file, |
||||
* allowing for configuring a DatabaseLogin instance as standard Spring bean |
||||
* definition (being able to leverage Spring's placeholder mechanism, etc). |
||||
* <p>The DatabaseLogin instance can either carry traditional JDBC config properties |
||||
* or hold a nested TopLink Connector instance, pointing to the connection pool to use. |
||||
* DatabaseLogin also holds the TopLink DatabasePlatform instance that defines the |
||||
* database product that TopLink is talking to (for example, HSQLPlatform). |
||||
* <p><b>WARNING:</b> Overriding the Login instance has been reported to not |
||||
* work on TopLink 10.1.3.0 and 10.1.3.1. Specify {@link #setLoginProperties |
||||
* "loginProperties"} or {@link #getLoginPropertyMap "loginPropertyMap[...]"} |
||||
* entries instead, if you prefer to have the login configuration defined |
||||
* on the Spring LocalSessionFactory. |
||||
*/ |
||||
public void setDatabaseLogin(DatabaseLogin databaseLogin) { |
||||
this.databaseLogin = databaseLogin; |
||||
} |
||||
|
||||
/** |
||||
* Specify TopLink login properties, to be passed to |
||||
* the {@link oracle.toplink.sessions.DatabaseLogin} instance. |
||||
* <p>Can be populated with a String "value" (parsed via PropertiesEditor) |
||||
* or a "props" element in XML bean definitions. |
||||
* @see oracle.toplink.sessions.DatabaseLogin |
||||
*/ |
||||
public void setLoginProperties(Properties loginProperties) { |
||||
CollectionUtils.mergePropertiesIntoMap(loginProperties, this.loginPropertyMap); |
||||
} |
||||
|
||||
/** |
||||
* Specify TopLink login properties as a Map, to be passed to |
||||
* the {@link oracle.toplink.sessions.DatabaseLogin} instance. |
||||
* <p>Can be populated with a "map" or "props" element in XML bean definitions. |
||||
* @see oracle.toplink.sessions.DatabaseLogin |
||||
*/ |
||||
public void setLoginPropertyMap(Map loginProperties) { |
||||
if (loginProperties != null) { |
||||
this.loginPropertyMap.putAll(loginProperties); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Allow Map access to the TopLink login properties to be passed to the |
||||
* DatabaseLogin instance, with the option to add or override specific entries. |
||||
* <p>Useful for specifying entries directly, for example via |
||||
* "loginPropertyMap[tableQualifier]". |
||||
* @see oracle.toplink.sessions.DatabaseLogin |
||||
*/ |
||||
public Map getLoginPropertyMap() { |
||||
return this.loginPropertyMap; |
||||
} |
||||
|
||||
/** |
||||
* Specify a standard JDBC DataSource that TopLink should use as connection pool. |
||||
* This allows for using a shared DataSource definition instead of TopLink's |
||||
* own connection pool. |
||||
* <p>A passed-in DataSource will be wrapped in an appropriate TopLink Connector |
||||
* and registered with the TopLink DatabaseLogin instance (either the default |
||||
* instance or one passed in through the "databaseLogin" property). The |
||||
* "usesExternalConnectionPooling" flag will automatically be set to "true". |
||||
* @see oracle.toplink.sessions.DatabaseLogin#setConnector(oracle.toplink.sessions.Connector) |
||||
* @see oracle.toplink.sessions.DatabaseLogin#setUsesExternalConnectionPooling(boolean) |
||||
* @see #setDatabaseLogin(oracle.toplink.sessions.DatabaseLogin) |
||||
*/ |
||||
public void setDataSource(DataSource dataSource) { |
||||
this.dataSource = dataSource; |
||||
} |
||||
|
||||
/** |
||||
* Specify the TopLink DatabasePlatform instance that the Session should use: |
||||
* for example, HSQLPlatform. This is an alternative to specifying the platform |
||||
* in a <login> tag in the <code>sessions.xml</code> configuration file. |
||||
* <p>A passed-in DatabasePlatform will be registered with the TopLink |
||||
* DatabaseLogin instance (either the default instance or one passed in |
||||
* through the "databaseLogin" property). |
||||
* @see oracle.toplink.internal.databaseaccess.HSQLPlatform |
||||
* @see oracle.toplink.platform.database.HSQLPlatform |
||||
*/ |
||||
public void setDatabasePlatform(DatabasePlatform databasePlatform) { |
||||
this.databasePlatform = databasePlatform; |
||||
} |
||||
|
||||
/** |
||||
* Specify a TopLink SessionLog instance to use for detailed logging of the |
||||
* Session's activities: for example, DefaultSessionLog (which logs to the |
||||
* console), JavaLog (which logs through JDK 1.4'S <code>java.util.logging</code>, |
||||
* available as of TopLink 10.1.3), or CommonsLoggingSessionLog / |
||||
* CommonsLoggingSessionLog904 (which logs through Commons Logging, |
||||
* on TopLink 10.1.3 and 9.0.4, respectively). |
||||
* <p>Note that detailed Session logging is usually only useful for debug |
||||
* logging, with adjustable detail level. As of TopLink 10.1.3, TopLink also |
||||
* uses different log categories, which allows for fine-grained filtering of |
||||
* log messages. For standard execution, no SessionLog needs to be specified. |
||||
* @see oracle.toplink.sessions.DefaultSessionLog |
||||
* @see oracle.toplink.logging.DefaultSessionLog |
||||
* @see oracle.toplink.logging.JavaLog |
||||
* @see org.springframework.orm.toplink.support.CommonsLoggingSessionLog |
||||
* @see org.springframework.orm.toplink.support.CommonsLoggingSessionLog904 |
||||
*/ |
||||
public void setSessionLog(SessionLog sessionLog) { |
||||
this.sessionLog = sessionLog; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Create a TopLink SessionFactory according to the configuration settings. |
||||
* @return the new TopLink SessionFactory |
||||
* @throws TopLinkException in case of errors |
||||
*/ |
||||
public SessionFactory createSessionFactory() throws TopLinkException { |
||||
if (logger.isInfoEnabled()) { |
||||
logger.info("Initializing TopLink SessionFactory from [" + this.configLocation + "]"); |
||||
} |
||||
|
||||
// Determine class loader to use.
|
||||
ClassLoader classLoader = |
||||
(this.sessionClassLoader != null ? this.sessionClassLoader : ClassUtils.getDefaultClassLoader()); |
||||
|
||||
// Initialize the TopLink Session, using the configuration file
|
||||
// and the session name.
|
||||
DatabaseSession session = loadDatabaseSession(this.configLocation, this.sessionName, classLoader); |
||||
|
||||
// It is possible for SessionManager to return a null Session!
|
||||
if (session == null) { |
||||
throw new IllegalStateException( |
||||
"A session named '" + this.sessionName + "' could not be loaded from resource [" + |
||||
this.configLocation + "] using ClassLoader [" + classLoader + "]. " + |
||||
"This is most likely a deployment issue: Can the class loader access the resource?"); |
||||
} |
||||
|
||||
DatabaseLogin login = (this.databaseLogin != null ? this.databaseLogin : session.getLogin()); |
||||
|
||||
// Apply specified login properties to the DatabaseLogin instance.
|
||||
if (this.loginPropertyMap != null) { |
||||
PropertyAccessorFactory.forBeanPropertyAccess(login).setPropertyValues(this.loginPropertyMap); |
||||
} |
||||
|
||||
// Override default connection pool with specified DataSource, if any.
|
||||
if (this.dataSource != null) { |
||||
login.setConnector(new JNDIConnector(this.dataSource)); |
||||
login.setUsesExternalConnectionPooling(true); |
||||
} |
||||
|
||||
// Override default DatabasePlatform with specified one, if any.
|
||||
if (this.databasePlatform != null) { |
||||
login.usePlatform(this.databasePlatform); |
||||
} |
||||
|
||||
// Override default DatabaseLogin instance with specified one, if any.
|
||||
if (this.databaseLogin != null) { |
||||
setDatabaseLogin(session, this.databaseLogin); |
||||
} |
||||
|
||||
// Override default SessionLog with specified one, if any.
|
||||
if (this.sessionLog != null) { |
||||
session.setSessionLog(this.sessionLog); |
||||
session.logMessages(); |
||||
} |
||||
|
||||
// Log in and create corresponding SessionFactory.
|
||||
session.login(); |
||||
return newSessionFactory(session); |
||||
} |
||||
|
||||
/** |
||||
* Handle differences between the <code>Session.setLogin</code> interface
|
||||
* between TopLink 9.0.4 to 10.1.3. |
||||
* <p>The Login interface was introduced in TopLink 10.1.3. |
||||
* @param session the DatabaseSession being logged in |
||||
* @param login the DatabaseLogin injected by Spring |
||||
* @see oracle.toplink.sessions.DatabaseSession#setLogin |
||||
*/ |
||||
protected void setDatabaseLogin(DatabaseSession session, DatabaseLogin login) { |
||||
Method setLoginMethod = null; |
||||
try { |
||||
// Search for the new 10.1.3 Login interface...
|
||||
Class loginClass = DatabaseSession.class.getClassLoader().loadClass("oracle.toplink.sessions.Login"); |
||||
setLoginMethod = DatabaseSession.class.getMethod("setLogin", new Class[] {loginClass}); |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Using TopLink 10.1.3 setLogin(Login) API"); |
||||
} |
||||
} |
||||
catch (Exception ex) { |
||||
// TopLink 10.1.3 Login interface not found ->
|
||||
// fall back to TopLink 9.0.4's setLogin(DatabaseLogin)
|
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Using TopLink 9.0.4 setLogin(DatabaseLogin) API"); |
||||
} |
||||
session.setLogin(login); |
||||
return; |
||||
} |
||||
|
||||
// Invoke the 10.1.3 version: Session.setLogin(Login)
|
||||
ReflectionUtils.invokeMethod(setLoginMethod, session, new Object[] {login}); |
||||
} |
||||
|
||||
/** |
||||
* Load the specified DatabaseSession from the TopLink <code>sessions.xml</code> |
||||
* configuration file. |
||||
* @param configLocation the class path location of the <code>sessions.xml</code> file |
||||
* @param sessionName the name of the TopLink Session in the configuration file |
||||
* @param sessionClassLoader the class loader to use |
||||
* @return the DatabaseSession instance |
||||
* @throws TopLinkException in case of errors |
||||
*/ |
||||
protected DatabaseSession loadDatabaseSession( |
||||
String configLocation, String sessionName, ClassLoader sessionClassLoader) |
||||
throws TopLinkException { |
||||
|
||||
SessionManager manager = getSessionManager(); |
||||
|
||||
// Try to find TopLink 10.1.3 XMLSessionConfigLoader.
|
||||
Method getSessionMethod = null; |
||||
Object loader = null; |
||||
try { |
||||
Class loaderClass = SessionManager.class.getClassLoader().loadClass( |
||||
"oracle.toplink.tools.sessionconfiguration.XMLSessionConfigLoader"); |
||||
getSessionMethod = SessionManager.class.getMethod("getSession", |
||||
new Class[] {loaderClass, String.class, ClassLoader.class, boolean.class, boolean.class, boolean.class}); |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Using TopLink 10.1.3 XMLSessionConfigLoader"); |
||||
} |
||||
Constructor ctor = loaderClass.getConstructor(new Class[] {String.class}); |
||||
loader = ctor.newInstance(new Object[] {configLocation}); |
||||
} |
||||
catch (Exception ex) { |
||||
// TopLink 10.1.3 XMLSessionConfigLoader not found ->
|
||||
// fall back to TopLink 9.0.4 XMLLoader.
|
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Using TopLink 9.0.4 XMLLoader"); |
||||
} |
||||
XMLLoader xmlLoader = new XMLLoader(configLocation); |
||||
return (DatabaseSession) manager.getSession(xmlLoader, sessionName, sessionClassLoader, false, false); |
||||
} |
||||
|
||||
// TopLink 10.1.3 XMLSessionConfigLoader found -> create loader instance
|
||||
// through reflection and fetch specified Session from SessionManager.
|
||||
// This invocation will check if the ClassLoader passed in is the same
|
||||
// as the one used to a session currently loaded with the same "sessionName"
|
||||
// If the ClassLoaders are different, then this LocalSessionFactory is being
|
||||
// re-loaded after a hot-deploy and the existing DatabaseSession will be logged
|
||||
// out and re-built from scratch.
|
||||
return (DatabaseSession) ReflectionUtils.invokeMethod(getSessionMethod, manager, |
||||
new Object[] {loader, sessionName, sessionClassLoader, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE}); |
||||
} |
||||
|
||||
/** |
||||
* Return the TopLink SessionManager to use for loading DatabaseSessions. |
||||
* <p>The default implementation creates a new plain SessionManager instance, |
||||
* leading to completely independent TopLink Session instances. Could be |
||||
* overridden to return a shared or pre-configured SessionManager. |
||||
* @return the TopLink SessionManager instance |
||||
*/ |
||||
protected SessionManager getSessionManager() { |
||||
return new SessionManager(); |
||||
} |
||||
|
||||
/** |
||||
* Create a new SessionFactory for the given TopLink DatabaseSession. |
||||
* <p>The default implementation creates a ServerSessionFactory for a |
||||
* ServerSession and a SingleSessionFactory for a plain DatabaseSession. |
||||
* @param session the TopLink DatabaseSession to create a SessionFactory for |
||||
* @return the SessionFactory |
||||
* @throws TopLinkException in case of errors |
||||
* @see ServerSessionFactory |
||||
* @see SingleSessionFactory |
||||
* @see oracle.toplink.threetier.ServerSession |
||||
* @see oracle.toplink.sessions.DatabaseSession |
||||
*/ |
||||
protected SessionFactory newSessionFactory(DatabaseSession session) { |
||||
if (session instanceof ServerSession) { |
||||
return new ServerSessionFactory((ServerSession) session); |
||||
} |
||||
else if (session instanceof SessionBroker) { |
||||
return new SessionBrokerSessionFactory((SessionBroker) session); |
||||
} |
||||
else { |
||||
return new SingleSessionFactory(session); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,160 +0,0 @@
@@ -1,160 +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.toplink; |
||||
|
||||
import java.sql.SQLException; |
||||
|
||||
import oracle.toplink.exceptions.DatabaseException; |
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
|
||||
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.dao.DataAccessException; |
||||
import org.springframework.dao.support.PersistenceExceptionTranslator; |
||||
import org.springframework.jdbc.support.SQLExceptionTranslator; |
||||
|
||||
/** |
||||
* {@link org.springframework.beans.factory.FactoryBean} that creates a |
||||
* TopLink {@link SessionFactory}. This is the usual way to set up a shared |
||||
* TopLink SessionFactory in a Spring application context; the SessionFactory |
||||
* can then be passed to TopLink-based DAOs via dependency injection. |
||||
* |
||||
* <p>See the base class {@link LocalSessionFactory} for configuration details. |
||||
* |
||||
* <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 LocalSessionFactoryBean automatically enables a |
||||
* PersistenceExceptionTranslationPostProcessor to translate TopLink exceptions. |
||||
* |
||||
* <p>If your DAOs expect to receive a raw TopLink Session, consider defining a |
||||
* {@link org.springframework.orm.toplink.support.TransactionAwareSessionAdapter} |
||||
* in front of this bean. This adapter will provide a TopLink Session rather |
||||
* than a SessionFactory as bean reference. Your DAOs can then, for example, |
||||
* access the currently active Session and UnitOfWork via |
||||
* <code>Session.getActiveSession()</code> and <code>Session.getActiveUnitOfWork()</code>, |
||||
* respectively. Note that you can still access the SessionFactory as well, by |
||||
* defining a bean reference that points directly at the LocalSessionFactoryBean. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see LocalSessionFactory |
||||
* @see org.springframework.orm.toplink.support.TransactionAwareSessionAdapter |
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor |
||||
*/ |
||||
public class LocalSessionFactoryBean extends LocalSessionFactory |
||||
implements FactoryBean, BeanClassLoaderAware, InitializingBean, DisposableBean, PersistenceExceptionTranslator { |
||||
|
||||
private SessionFactory sessionFactory; |
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator; |
||||
|
||||
|
||||
/** |
||||
* Set the JDBC exception translator for this SessionFactory. |
||||
* <p>Applied to any SQLException root cause of a TopLink DatabaseException, |
||||
* within Spring's PersistenceExceptionTranslator mechanism. |
||||
* The default is to rely on TopLink's native exception translation. |
||||
* @see oracle.toplink.exceptions.DatabaseException |
||||
* @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 instance, if any. |
||||
*/ |
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() { |
||||
return this.jdbcExceptionTranslator; |
||||
} |
||||
|
||||
/** |
||||
* Sets the given bean ClassLoader as TopLink Session ClassLoader. |
||||
* @see #setSessionClassLoader |
||||
*/ |
||||
public void setBeanClassLoader(ClassLoader classLoader) { |
||||
setSessionClassLoader(classLoader); |
||||
} |
||||
|
||||
public void afterPropertiesSet() throws TopLinkException { |
||||
this.sessionFactory = createSessionFactory(); |
||||
} |
||||
|
||||
|
||||
public Object getObject() { |
||||
return this.sessionFactory; |
||||
} |
||||
|
||||
public Class getObjectType() { |
||||
return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class); |
||||
} |
||||
|
||||
public boolean isSingleton() { |
||||
return true; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Implementation of the PersistenceExceptionTranslator interface, |
||||
* as autodetected by Spring's PersistenceExceptionTranslationPostProcessor. |
||||
* <p>Converts the exception if it is a TopLinkException; |
||||
* else returns <code>null</code> to indicate an unknown exception. |
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor |
||||
* @see #convertTopLinkAccessException |
||||
*/ |
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) { |
||||
if (ex instanceof TopLinkException) { |
||||
return convertTopLinkAccessException((TopLinkException) ex); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Convert the given TopLinkException to an appropriate exception from the |
||||
* <code>org.springframework.dao</code> hierarchy. |
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a |
||||
* TopLink DatabaseException, else rely on TopLink's default translation. |
||||
* @param ex TopLinkException that occured |
||||
* @return a corresponding DataAccessException |
||||
* @see SessionFactoryUtils#convertTopLinkAccessException |
||||
* @see #setJdbcExceptionTranslator |
||||
*/ |
||||
public DataAccessException convertTopLinkAccessException(TopLinkException ex) { |
||||
if (getJdbcExceptionTranslator() != null && ex instanceof DatabaseException) { |
||||
Throwable internalEx = ex.getInternalException(); |
||||
// Should always be a SQLException inside a DatabaseException.
|
||||
if (internalEx instanceof SQLException) { |
||||
return getJdbcExceptionTranslator().translate( |
||||
"TopLink operation: " + ex.getMessage(), null, (SQLException) internalEx); |
||||
} |
||||
} |
||||
return SessionFactoryUtils.convertTopLinkAccessException(ex); |
||||
} |
||||
|
||||
|
||||
public void destroy() { |
||||
logger.info("Closing TopLink SessionFactory"); |
||||
this.sessionFactory.close(); |
||||
} |
||||
|
||||
} |
||||
@ -1,82 +0,0 @@
@@ -1,82 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.threetier.ServerSession; |
||||
|
||||
/** |
||||
* Full-fledged default implementation of the SessionFactory interface: |
||||
* creates ClientSessions for a given ServerSession. |
||||
* |
||||
* <p>Can create a special ClientSession subclass for managed Sessions, carrying |
||||
* an active UnitOfWork that expects to be committed at transaction completion |
||||
* (just like a plain TopLink Session does within a JTA transaction). |
||||
* |
||||
* <p>Can also create a transaction-aware Session reference that returns the |
||||
* active transactional Session on <code>getActiveSession</code>. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see SingleSessionFactory |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
* @see oracle.toplink.sessions.Session#getActiveSession() |
||||
*/ |
||||
public class ServerSessionFactory extends AbstractSessionFactory { |
||||
|
||||
private final ServerSession serverSession; |
||||
|
||||
|
||||
/** |
||||
* Create a new ServerSessionFactory for the given ServerSession. |
||||
* @param serverSession the TopLink ServerSession to create ClientSessions for |
||||
*/ |
||||
public ServerSessionFactory(ServerSession serverSession) { |
||||
this.serverSession = serverSession; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return this factory's ServerSession as-is. |
||||
*/ |
||||
@Override |
||||
protected Session getMasterSession() { |
||||
return this.serverSession; |
||||
} |
||||
|
||||
/** |
||||
* Create a plain ClientSession for this factory's ServerSession. |
||||
* @see oracle.toplink.threetier.ServerSession#acquireClientSession() |
||||
*/ |
||||
@Override |
||||
protected Session createClientSession() throws TopLinkException { |
||||
return this.serverSession.acquireClientSession(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shut the pre-configured TopLink ServerSession down. |
||||
* @see oracle.toplink.sessions.DatabaseSession#logout() |
||||
* @see oracle.toplink.sessions.Session#release() |
||||
*/ |
||||
public void close() { |
||||
this.serverSession.logout(); |
||||
this.serverSession.release(); |
||||
} |
||||
|
||||
} |
||||
@ -1,109 +0,0 @@
@@ -1,109 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.exceptions.ValidationException; |
||||
import oracle.toplink.sessionbroker.SessionBroker; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
/** |
||||
* Spring SessionFactory implementation allowing users to |
||||
* inject a TopLink Session built from a TopLink SessionBroker. |
||||
* |
||||
* SessionBrokers are used identically to any other TopLink Session. DAO code |
||||
* should never have to distinguish between Sessions which broker requests to |
||||
* multiple databases and Sessions which manage requests to a single database. |
||||
* |
||||
* The only pertinent difference in the SessionBroker api involves the method |
||||
* for obtaining a thread-safe "client" Session from the SessionBroker. |
||||
* Instead of the typical acquireClientSession |
||||
* method, this SessionFactory implementation uses the |
||||
* acquireClientSessionBroker method. |
||||
* If a SessionBroker aggregates non thread-safe DatabaseSessions, |
||||
* the factory will throw UnsupportedOperationExceptions |
||||
* if used to create managed or transaction-aware Sessions. |
||||
* |
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a> |
||||
* @author Juergen Hoeller |
||||
* @since 1.2.6 |
||||
* @see org.springframework.orm.toplink.ServerSessionFactory |
||||
* @see oracle.toplink.threetier.ServerSession#acquireClientSession() |
||||
* @see oracle.toplink.sessionbroker.SessionBroker#acquireClientSessionBroker() |
||||
*/ |
||||
public class SessionBrokerSessionFactory extends AbstractSessionFactory { |
||||
|
||||
private final SessionBroker sessionBroker; |
||||
|
||||
|
||||
/** |
||||
* Create a new SessionBrokerSessionFactory for the given SessionBroker. |
||||
* @param broker the TopLink SessionBroker to fetch Sessions from |
||||
*/ |
||||
public SessionBrokerSessionFactory(SessionBroker broker) { |
||||
this.sessionBroker = broker; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Try to create a client Session; fall back to the master Session, |
||||
* if no client Session can be created (because of the session broker's |
||||
* configuration). |
||||
* @see #createClientSession() |
||||
* @see #getMasterSession() |
||||
*/ |
||||
@Override |
||||
public Session createSession() throws TopLinkException { |
||||
try { |
||||
return createClientSession(); |
||||
} |
||||
catch (ValidationException ex) { |
||||
logger.debug( |
||||
"Could not create TopLink client session for SessionBroker - returning SessionBroker itself", ex); |
||||
return getMasterSession(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return this factory's SessionBroker as-is. |
||||
*/ |
||||
@Override |
||||
protected Session getMasterSession() { |
||||
return this.sessionBroker; |
||||
} |
||||
|
||||
/** |
||||
* Create a plain client SessionBroker for this factory's ServerSession. |
||||
* @see oracle.toplink.sessionbroker.SessionBroker#acquireClientSessionBroker() |
||||
*/ |
||||
@Override |
||||
protected Session createClientSession() throws TopLinkException { |
||||
return this.sessionBroker.acquireClientSessionBroker(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shut the pre-configured TopLink SessionBroker down. |
||||
* @see oracle.toplink.sessions.DatabaseSession#logout() |
||||
* @see oracle.toplink.sessions.Session#release() |
||||
*/ |
||||
public void close() { |
||||
this.sessionBroker.logout(); |
||||
this.sessionBroker.release(); |
||||
} |
||||
|
||||
} |
||||
@ -1,95 +0,0 @@
@@ -1,95 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
/** |
||||
* The SessionFactory interface serves as factory for TopLink Sessions, |
||||
* allowing for dependency injection on thread-safe TopLink-based DAOs. |
||||
* Used by TopLinkAccessor/Template and TopLinkTransactionManager. |
||||
* |
||||
* <p>In contrast to JDO or Hibernate (which define native PersistenceManagerFactory |
||||
* and SessionFactory interfaces, respectively), TopLink itself does not provide |
||||
* such a factory interface: hence, it is necessary to define it within Spring. |
||||
* Note that this interface does not depend on any other Spring interfaces or |
||||
* classes, to allow for keeping TopLink-based DAOs as independent as possible. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see TopLinkAccessor#setSessionFactory |
||||
* @see TopLinkTransactionManager#setSessionFactory |
||||
*/ |
||||
public interface SessionFactory { |
||||
|
||||
/** |
||||
* Create a plain TopLink Session for the current application context. |
||||
* Will usually be a new ClientSession for the current thread. |
||||
* <p>The returned Session will participate in JTA transactions (provided that |
||||
* TopLink is configured with a corresponding external transaction controller), |
||||
* but not in Spring-managed transactions (by TopLinkTransactionManager). |
||||
* <p>This is the factory method to be called by TopLink data access code, |
||||
* usually through the <code>SessionFactoryUtils.getSession</code> method |
||||
* that checks for a transactional (thread-bound) Session first. |
||||
* @return the new TopLink Session |
||||
* @throws TopLinkException in case of errors |
||||
* @see SessionFactoryUtils#getSession(SessionFactory, boolean) |
||||
*/ |
||||
Session createSession() throws TopLinkException; |
||||
|
||||
/** |
||||
* Create a new managed TopLink client Session for the current context. |
||||
* Will usually be a new special ClientSession for the current thread. |
||||
* <p>The returned Session will be prepared to be managed within a Spring |
||||
* transaction (by TopLinkTransactionManager). It will carry an active |
||||
* UnitOfWork that expects to be committed at transaction completion, |
||||
* just like a plain TopLink Session does within a JTA transaction. |
||||
* <p>This method is only supposed to be called by Spring's |
||||
* TopLinkTransactionManager or similar TopLink-based transaction managers. |
||||
* If a SessionFactory does not support managed Sessions, it should throw |
||||
* an UnsupportedOperationException. |
||||
* @return the new TopLink Session |
||||
* @throws TopLinkException in case of errors |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
Session createManagedClientSession() throws TopLinkException; |
||||
|
||||
/** |
||||
* Create a new transaction-aware TopLink Session that exposes the currently |
||||
* active Session and UnitOfWork via <code>Session.getActiveSession()</code> |
||||
* and <code>Session.getActiveUnitOfWork()</code>, respectively. |
||||
* <p>Such a Session reference can be used analogously to a managed TopLink |
||||
* Session in a JTA environment, with Spring-managed transactions backing it. |
||||
* <p>It is usually preferable to let DAOs work with a full SessionFactory, |
||||
* accessing TopLink Sessions via <code>SessionFactoryUtils.getSession</code>. |
||||
* However, a transaction-aware TopLink Session reference does not impose any |
||||
* Spring dependency, so might be preferable if you'd like to keep your data |
||||
* access code tied to TopLink API only. |
||||
* @return the new TopLink Session |
||||
* @throws TopLinkException in case of errors |
||||
* @see oracle.toplink.sessions.Session#getActiveSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
Session createTransactionAwareSession() throws TopLinkException; |
||||
|
||||
/** |
||||
* Close this SessionFactory, shutting down all internal resources. |
||||
*/ |
||||
void close(); |
||||
|
||||
} |
||||
@ -1,237 +0,0 @@
@@ -1,237 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2008 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.ConcurrencyException; |
||||
import oracle.toplink.exceptions.ConversionException; |
||||
import oracle.toplink.exceptions.DatabaseException; |
||||
import oracle.toplink.exceptions.OptimisticLockException; |
||||
import oracle.toplink.exceptions.QueryException; |
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.dao.ConcurrencyFailureException; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.dao.DataAccessResourceFailureException; |
||||
import org.springframework.dao.TypeMismatchDataAccessException; |
||||
import org.springframework.transaction.support.ResourceHolder; |
||||
import org.springframework.transaction.support.ResourceHolderSynchronization; |
||||
import org.springframework.transaction.support.TransactionSynchronizationManager; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Helper class featuring methods for TopLink Session handling, |
||||
* allowing for reuse of TopLink Session instances within transactions. |
||||
* Also provides support for exception translation. |
||||
* |
||||
* <p>Mainly intended for internal use within the framework. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a> |
||||
* @since 1.2 |
||||
*/ |
||||
public abstract class SessionFactoryUtils { |
||||
|
||||
private static final Log logger = LogFactory.getLog(SessionFactoryUtils.class); |
||||
|
||||
|
||||
/** |
||||
* Get a TopLink Session for the given SessionFactory. Is aware of and will |
||||
* return any existing corresponding Session bound to the current thread, for |
||||
* example when using TopLinkTransactionManager. Will create a new Session |
||||
* otherwise, if "allowCreate" is <code>true</code>. |
||||
* <p>This is the <code>getSession</code> method used by typical data access code, |
||||
* in combination with <code>releaseSession</code> called when done with |
||||
* the Session. Note that TopLinkTemplate allows to write data access code |
||||
* without caring about such resource handling. |
||||
* @param sessionFactory TopLink SessionFactory to create the session with |
||||
* @param allowCreate if a non-transactional Session should be created when no |
||||
* transactional Session can be found for the current thread |
||||
* @return the TopLink Session |
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created |
||||
* @throws IllegalStateException if no thread-bound Session found and |
||||
* "allowCreate" is <code>false</code> |
||||
* @see #releaseSession |
||||
* @see TopLinkTemplate |
||||
*/ |
||||
public static Session getSession(SessionFactory sessionFactory, boolean allowCreate) |
||||
throws DataAccessResourceFailureException, IllegalStateException { |
||||
|
||||
try { |
||||
return doGetSession(sessionFactory, allowCreate); |
||||
} |
||||
catch (TopLinkException ex) { |
||||
throw new DataAccessResourceFailureException("Could not open TopLink Session", ex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get a TopLink Session for the given SessionFactory. Is aware of and will |
||||
* return any existing corresponding Session bound to the current thread, for |
||||
* example when using TopLinkTransactionManager. Will create a new Session |
||||
* otherwise, if "allowCreate" is <code>true</code>. |
||||
* <p>Same as <code>getSession</code>, but throwing the original TopLinkException. |
||||
* @param sessionFactory TopLink SessionFactory to create the session with |
||||
* @param allowCreate if a non-transactional Session should be created when no |
||||
* transactional Session can be found for the current thread |
||||
* @return the TopLink Session |
||||
* @throws TopLinkException if the Session couldn't be created |
||||
* @throws IllegalStateException if no thread-bound Session found and |
||||
* "allowCreate" is <code>false</code> |
||||
* @see #releaseSession |
||||
* @see TopLinkTemplate |
||||
*/ |
||||
public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate) |
||||
throws TopLinkException, IllegalStateException { |
||||
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified"); |
||||
|
||||
SessionHolder sessionHolder = |
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); |
||||
if (sessionHolder != null) { |
||||
return sessionHolder.getSession(); |
||||
} |
||||
|
||||
if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) { |
||||
throw new IllegalStateException("No TopLink Session bound to thread, " + |
||||
"and configuration does not allow creation of non-transactional one here"); |
||||
} |
||||
|
||||
logger.debug("Creating TopLink Session"); |
||||
Session session = sessionFactory.createSession(); |
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) { |
||||
logger.debug("Registering new Spring transaction synchronization for new TopLink Session"); |
||||
// Use same Session for further TopLink actions within the transaction.
|
||||
// Thread object will get removed by synchronization at transaction completion.
|
||||
sessionHolder = new SessionHolder(session); |
||||
sessionHolder.setSynchronizedWithTransaction(true); |
||||
TransactionSynchronizationManager.registerSynchronization( |
||||
new SessionSynchronization(sessionHolder, sessionFactory)); |
||||
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); |
||||
} |
||||
|
||||
return session; |
||||
} |
||||
|
||||
/** |
||||
* Return whether the given TopLink Session is transactional, that is, |
||||
* bound to the current thread by Spring's transaction facilities. |
||||
* @param session the TopLink Session to check |
||||
* @param sessionFactory TopLink SessionFactory that the Session was created with |
||||
* (can be <code>null</code>) |
||||
* @return whether the Session is transactional |
||||
*/ |
||||
public static boolean isSessionTransactional(Session session, SessionFactory sessionFactory) { |
||||
if (sessionFactory == null) { |
||||
return false; |
||||
} |
||||
SessionHolder sessionHolder = |
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); |
||||
return (sessionHolder != null && session == sessionHolder.getSession()); |
||||
} |
||||
|
||||
/** |
||||
* Convert the given TopLinkException to an appropriate exception from the |
||||
* <code>org.springframework.dao</code> hierarchy. |
||||
* @param ex TopLinkException that occured |
||||
* @return the corresponding DataAccessException instance |
||||
*/ |
||||
public static DataAccessException convertTopLinkAccessException(TopLinkException ex) { |
||||
if (ex instanceof DatabaseException) { |
||||
// SQLException during TopLink access: only passed in here from custom code,
|
||||
// as TopLinkTemplate will use SQLExceptionTranslator-based handling.
|
||||
return new TopLinkJdbcException((DatabaseException) ex); |
||||
} |
||||
if (ex instanceof OptimisticLockException) { |
||||
return new TopLinkOptimisticLockingFailureException((OptimisticLockException) ex); |
||||
} |
||||
if (ex instanceof QueryException) { |
||||
return new TopLinkQueryException((QueryException) ex); |
||||
} |
||||
if (ex instanceof ConcurrencyException) { |
||||
return new ConcurrencyFailureException(ex.getMessage(), ex); |
||||
} |
||||
if (ex instanceof ConversionException) { |
||||
return new TypeMismatchDataAccessException(ex.getMessage(), ex); |
||||
} |
||||
// fallback
|
||||
return new TopLinkSystemException(ex); |
||||
} |
||||
|
||||
/** |
||||
* Close the given Session, created via the given factory, |
||||
* if it is not managed externally (i.e. not bound to the thread). |
||||
* @param session the TopLink Session to close |
||||
* @param sessionFactory TopLink SessionFactory that the Session was created with |
||||
* (can be <code>null</code>) |
||||
*/ |
||||
public static void releaseSession(Session session, SessionFactory sessionFactory) { |
||||
if (session == null) { |
||||
return; |
||||
} |
||||
// Only release non-transactional Sessions.
|
||||
if (!isSessionTransactional(session, sessionFactory)) { |
||||
doRelease(session); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Perform the actual releasing of the TopLink Session. |
||||
* @param session the TopLink Session to release |
||||
*/ |
||||
private static void doRelease(Session session) { |
||||
if (session != null) { |
||||
logger.debug("Closing TopLink Session"); |
||||
try { |
||||
session.release(); |
||||
} |
||||
catch (TopLinkException ex) { |
||||
logger.debug("Could not close TopLink Session", ex); |
||||
} |
||||
catch (Throwable ex) { |
||||
logger.debug("Unexpected exception on closing TopLink Session", ex); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Callback for resource cleanup at the end of a Spring-managed JTA transaction, |
||||
* i.e. when participating in a JtaTransactionManager transaction. |
||||
* @see org.springframework.transaction.jta.JtaTransactionManager |
||||
*/ |
||||
private static class SessionSynchronization extends ResourceHolderSynchronization { |
||||
|
||||
public SessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory) { |
||||
super(sessionHolder, sessionFactory); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean shouldReleaseBeforeCompletion() { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) { |
||||
releaseSession(((SessionHolder) resourceHolder).getSession(), (SessionFactory) resourceKey); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,55 +0,0 @@
@@ -1,55 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Session holder, wrapping a TopLink Session. |
||||
* TopLinkTransactionManager binds instances of this class
|
||||
* to the thread, for a given SessionFactory. |
||||
* |
||||
* <p>Note: This is an SPI class, not intended to be used by applications. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
*/ |
||||
public class SessionHolder extends ResourceHolderSupport { |
||||
|
||||
private final Session session; |
||||
|
||||
|
||||
/** |
||||
* Create a new SessionHolder for the given TopLink Session. |
||||
* @param session the TopLink Session |
||||
*/ |
||||
public SessionHolder(Session session) { |
||||
Assert.notNull(session, "Session must not be null"); |
||||
this.session = session; |
||||
} |
||||
|
||||
/** |
||||
* Return this holder's TopLink Session. |
||||
*/ |
||||
public Session getSession() { |
||||
return session; |
||||
} |
||||
|
||||
} |
||||
@ -1,87 +0,0 @@
@@ -1,87 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.sessions.UnitOfWork; |
||||
|
||||
/** |
||||
* Convenient abstract implementation of the TopLinkCallback interface, |
||||
* exposing either the plain TopLink Session or the TopLink UnitOfWork |
||||
* (which extends the Session interface) to code that reads persistent objects. |
||||
* |
||||
* <p>Exposes the UnitOfWork if there is an active one (that is, if we're running |
||||
* within a non-read-only transaction); else exposes the Session itself. |
||||
* This allows to modify returned objects within a transaction, which is |
||||
* often desired, while the same code will return shared cache objects |
||||
* if running outside a transaction. |
||||
* |
||||
* <p>If "enforceReadOnly" is demanded, the callback will always expose the |
||||
* Session itself, avoiding the UnitOfWork overhead in any case. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
* @see #readFromSession(oracle.toplink.sessions.Session) |
||||
*/ |
||||
public abstract class SessionReadCallback implements TopLinkCallback { |
||||
|
||||
private final boolean enforceReadOnly; |
||||
|
||||
/** |
||||
* Create a new SessionReadCallback, not enforcing read-only objects. |
||||
*/ |
||||
public SessionReadCallback() { |
||||
this.enforceReadOnly = false; |
||||
} |
||||
|
||||
/** |
||||
* Create a new SessionReadCallback, enforcing read-only objects if demanded. |
||||
* @param enforceReadOnly whether to enforce returning read-only objects, |
||||
* even if running within a non-read-only transaction |
||||
*/ |
||||
public SessionReadCallback(boolean enforceReadOnly) { |
||||
this.enforceReadOnly = enforceReadOnly; |
||||
} |
||||
|
||||
/** |
||||
* Determines the Session to work on (either the active UnitOfWork |
||||
* or the plain Session) and delegates to <code>readFromSession</code>. |
||||
* @see #readFromSession(oracle.toplink.sessions.Session) |
||||
*/ |
||||
public final Object doInTopLink(Session session) throws TopLinkException { |
||||
Session sessionToUse = session; |
||||
if (!this.enforceReadOnly) { |
||||
UnitOfWork unitOfWork = session.getActiveUnitOfWork(); |
||||
if (unitOfWork != null) { |
||||
sessionToUse = unitOfWork; |
||||
} |
||||
} |
||||
return readFromSession(sessionToUse); |
||||
} |
||||
|
||||
/** |
||||
* Called with a Session to work on, either the active UnitOfWork |
||||
* or the plain Session (as determined by the transaction status). |
||||
* @param session the TopLink Session to perform read operations on |
||||
* @return a result object, or <code>null</code> if none |
||||
* @throws TopLinkException in case of TopLink errors |
||||
*/ |
||||
protected abstract Object readFromSession(Session session) throws TopLinkException; |
||||
|
||||
} |
||||
@ -1,83 +0,0 @@
@@ -1,83 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.sessions.DatabaseSession; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
/** |
||||
* Simple implementation of the SessionFactory interface: always returns |
||||
* the passed-in Session as-is. |
||||
* |
||||
* <p>Useful for testing or standalone usage of TopLink-based data access objects. |
||||
* <b>In a server environment, use ServerSessionFactory instead.</code> |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see ServerSessionFactory |
||||
*/ |
||||
public class SingleSessionFactory implements SessionFactory { |
||||
|
||||
private final Session session; |
||||
|
||||
|
||||
/** |
||||
* Create a new SingleSessionFactory with the given Session. |
||||
* @param session the TopLink Session to hold |
||||
*/ |
||||
public SingleSessionFactory(Session session) { |
||||
this.session = session; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return the held TopLink Session as-is. |
||||
*/ |
||||
public Session createSession() { |
||||
return this.session; |
||||
} |
||||
|
||||
/** |
||||
* Throws an UnsupportedOperationException: SingleSessionFactory does not |
||||
* support managed client Sessions. Use ServerSessionFactory instead. |
||||
*/ |
||||
public Session createManagedClientSession() { |
||||
throw new UnsupportedOperationException("SingleSessionFactory does not support managed client Sessions"); |
||||
} |
||||
|
||||
/** |
||||
* Throws an UnsupportedOperationException: SingleSessionFactory does not |
||||
* support transaction-aware Sessions. Use ServerSessionFactory instead. |
||||
*/ |
||||
public Session createTransactionAwareSession() { |
||||
throw new UnsupportedOperationException("SingleSessionFactory does not support transaction-aware Sessions"); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Shut the pre-configured TopLink Session down. |
||||
* @see oracle.toplink.sessions.DatabaseSession#logout() |
||||
* @see oracle.toplink.sessions.Session#release() |
||||
*/ |
||||
public void close() { |
||||
if (this.session instanceof DatabaseSession) { |
||||
((DatabaseSession) this.session).logout(); |
||||
} |
||||
this.session.release(); |
||||
} |
||||
|
||||
} |
||||
@ -1,131 +0,0 @@
@@ -1,131 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import java.sql.SQLException; |
||||
|
||||
import oracle.toplink.exceptions.DatabaseException; |
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.jdbc.support.SQLExceptionTranslator; |
||||
|
||||
/** |
||||
* Base class for TopLinkTemplate and TopLinkInterceptor, defining common properties |
||||
* such as SessionFactory and JDBC exception translator. |
||||
* |
||||
* <p>Not intended to be used directly. See TopLinkTemplate and TopLinkInterceptor. |
||||
* |
||||
* <p>Thanks to Slavik Markovich for implementing the initial TopLink support prototype! |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see TopLinkTemplate |
||||
* @see TopLinkInterceptor |
||||
*/ |
||||
public abstract class TopLinkAccessor implements InitializingBean { |
||||
|
||||
/** Logger available to subclasses */ |
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
private SessionFactory sessionFactory; |
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator; |
||||
|
||||
|
||||
/** |
||||
* Set the the TopLink SessionFactory that should be used to create TopLink |
||||
* Sessions. This will usually be a ServerSessionFactory in a multi-threaded |
||||
* environment, but can also be a SingleSessionFactory for testing purposes |
||||
* or for standalone execution. |
||||
* <p>The passed-in SessionFactory will usually be asked for a plain Session |
||||
* to perform data access on, unless an active transaction with a thread-bound |
||||
* Session is found. |
||||
* @see ServerSessionFactory |
||||
* @see SingleSessionFactory |
||||
* @see SessionFactory#createSession() |
||||
* @see SessionFactoryUtils#getSession(SessionFactory, boolean) |
||||
*/ |
||||
public void setSessionFactory(SessionFactory sessionFactory) { |
||||
this.sessionFactory = sessionFactory; |
||||
} |
||||
|
||||
/** |
||||
* Return the TopLink SessionFactory that should be used to create |
||||
* TopLink Sessions. |
||||
*/ |
||||
public SessionFactory getSessionFactory() { |
||||
return sessionFactory; |
||||
} |
||||
|
||||
/** |
||||
* Set the JDBC exception translator for this instance. |
||||
* <p>Applied to any SQLException root cause of a TopLink DatabaseException. |
||||
* The default is to rely on TopLink's native exception translation. |
||||
* @param jdbcExceptionTranslator the exception translator |
||||
* @see oracle.toplink.exceptions.DatabaseException |
||||
* @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 instance, if any. |
||||
*/ |
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() { |
||||
return this.jdbcExceptionTranslator; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Check that we were provided with a session to use |
||||
*/ |
||||
public void afterPropertiesSet() { |
||||
if (this.sessionFactory == null) { |
||||
throw new IllegalArgumentException("sessionFactory is required"); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Convert the given TopLinkException to an appropriate exception from the |
||||
* <code>org.springframework.dao</code> hierarchy. |
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a |
||||
* TopLink DatabaseException, else rely on TopLink's default translation. |
||||
* @param ex TopLinkException that occured |
||||
* @return a corresponding DataAccessException |
||||
* @see SessionFactoryUtils#convertTopLinkAccessException |
||||
* @see #setJdbcExceptionTranslator |
||||
*/ |
||||
public DataAccessException convertTopLinkAccessException(TopLinkException ex) { |
||||
if (getJdbcExceptionTranslator() != null && ex instanceof DatabaseException) { |
||||
Throwable internalEx = ex.getInternalException(); |
||||
// Should always be a SQLException inside a DatabaseException.
|
||||
if (internalEx instanceof SQLException) { |
||||
return getJdbcExceptionTranslator().translate( |
||||
"TopLink operation: " + ex.getMessage(), null, (SQLException) internalEx); |
||||
} |
||||
} |
||||
return SessionFactoryUtils.convertTopLinkAccessException(ex); |
||||
} |
||||
|
||||
} |
||||
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
/** |
||||
* Callback interface for TopLink code. To be used with {@link TopLinkTemplate}'s |
||||
* execution methods, often as anonymous classes within a method implementation. |
||||
* A typical implementation will call TopLink Session CRUD to perform some |
||||
* operations on persistent objects. |
||||
* |
||||
* <p>The <code>Session</code> that gets passed into the <code>doInTopLink</code> method |
||||
* is usually a thread-safe <code>ClientSession</code>. Since this provides access to the |
||||
* TopLink shared cache, it is possible for implementations of this interface to return |
||||
* references to <i>read-only objects from the shared cache</i>. These objects |
||||
* <i>must not be modified</i> by application code outside of the DAO layer. |
||||
* If persistent objects need to be edited, they should be loaded from (or registered with) |
||||
* a TopLink UnitOfWork, or they should be explicitly copied and merged back into a |
||||
* <code>UnitOfWork</code> at a later point of time. |
||||
* |
||||
* <p>Users can access a <code>UnitOfWork</code> by using the <code>getActiveUnitOfWork</code> |
||||
* method on the <code>Session</code>. Normally, this will only be done when there is an |
||||
* active non-read-only transaction being managed by Spring's {@link TopLinkTransactionManager} |
||||
* or by an external transaction controller (usually a J2EE server's JTA provider, |
||||
* configured in TopLink). The <code>getActiveUnitOfWork</code> method will return |
||||
* <code>null</code> outside of a managed transaction. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author <a href="mailto:@james.x.clark@oracle.com">James Clark</a> |
||||
* @see TopLinkTemplate |
||||
* @see TopLinkTransactionManager |
||||
*/ |
||||
public interface TopLinkCallback { |
||||
|
||||
/** |
||||
* Gets called by <code>TopLinkTemplate.execute</code> with an active |
||||
* <code>Session</code>. Does not need to care about activating or closing |
||||
* the TopLink <code>Session</code>, or handling transactions. |
||||
* |
||||
* <p>Note that write operations should usually be performed on the active |
||||
* <code>UnitOfWork</code> within an externally controlled transaction, through |
||||
* calling <code>getActiveUnitOfWork</code>. However, an implementation can also |
||||
* choose to use <code>acquireUnitOfWork</code> to create an independent |
||||
* <code>UnitOfWork</code>, which it needs to commit at the end of the operation. |
||||
* |
||||
* <p>Allows for returning a result object created within the callback, |
||||
* i.e. a domain object or a collection of domain objects. |
||||
* A thrown custom RuntimeException is treated as an application exception: |
||||
* It gets propagated to the caller of the template. |
||||
* |
||||
* @param session active TopLink Session |
||||
* @return a result object, or <code>null</code> if none |
||||
* @throws TopLinkException if thrown by the TopLink API |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
* @see oracle.toplink.sessions.Session#acquireUnitOfWork() |
||||
* @see TopLinkTemplate#execute |
||||
* @see TopLinkTemplate#executeFind |
||||
*/ |
||||
Object doInTopLink(Session session) throws TopLinkException; |
||||
|
||||
} |
||||
@ -1,117 +0,0 @@
@@ -1,117 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import org.aopalliance.intercept.MethodInterceptor; |
||||
import org.aopalliance.intercept.MethodInvocation; |
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager; |
||||
|
||||
/** |
||||
* This interceptor binds a new TopLink Session to the thread before a method |
||||
* call, closing and removing it afterwards in case of any method outcome. |
||||
* If there already is a pre-bound Session (e.g. from TopLinkTransactionManager, |
||||
* or from a surrounding TopLink-intercepted method), the interceptor simply |
||||
* takes part in it. |
||||
* |
||||
* <p>Application code must retrieve a TopLink Session via the |
||||
* <code>SessionFactoryUtils.getSession</code> method or - preferably - |
||||
* TopLink's own <code>Session.getActiveSession()</code> method, to be able to |
||||
* detect a thread-bound Session. Typically, the code will look like as follows: |
||||
* |
||||
* <pre> |
||||
* public void doSomeDataAccessAction() { |
||||
* Session session = this.serverSession.getActiveSession(); |
||||
* ... |
||||
* }</pre> |
||||
* |
||||
* Note that this interceptor automatically translates TopLinkExceptions, |
||||
* via delegating to the <code>SessionFactoryUtils.convertTopLikAccessException</code> |
||||
* method that converts them to exceptions that are compatible with the |
||||
* <code>org.springframework.dao</code> exception hierarchy (like TopLinkTemplate does). |
||||
* This can be turned off if the raw exceptions are preferred. |
||||
* |
||||
* <p>This class can be considered a declarative alternative to TopLinkTemplate's |
||||
* callback approach. The advantages are: |
||||
* <ul> |
||||
* <li>no anonymous classes necessary for callback implementations; |
||||
* <li>the possibility to throw any application exceptions from within data access code. |
||||
* </ul> |
||||
* |
||||
* <p>The drawback is the dependency on interceptor configuration. However, note |
||||
* that this interceptor is usually <i>not</i> necessary in scenarios where the |
||||
* data access code always executes within transactions. A transaction will always |
||||
* have a thread-bound Session in the first place, so adding this interceptor to the |
||||
* configuration just adds value when potentially executing outside of transactions |
||||
* and/or when relying on exception translation. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
*/ |
||||
public class TopLinkInterceptor extends TopLinkAccessor implements MethodInterceptor { |
||||
|
||||
private boolean exceptionConversionEnabled = true; |
||||
|
||||
|
||||
/** |
||||
* Set whether to convert any TopLinkException raised to a Spring DataAccessException, |
||||
* compatible with the <code>org.springframework.dao</code> exception hierarchy. |
||||
* <p>Default is "true". Turn this flag off to let the caller receive raw exceptions |
||||
* as-is, without any wrapping. |
||||
* @see org.springframework.dao.DataAccessException |
||||
*/ |
||||
public void setExceptionConversionEnabled(boolean exceptionConversionEnabled) { |
||||
this.exceptionConversionEnabled = exceptionConversionEnabled; |
||||
} |
||||
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable { |
||||
boolean existingTransaction = false; |
||||
Session session = SessionFactoryUtils.getSession(getSessionFactory(), true); |
||||
if (TransactionSynchronizationManager.hasResource(getSessionFactory())) { |
||||
logger.debug("Found thread-bound Session for TopLink interceptor"); |
||||
existingTransaction = true; |
||||
} |
||||
else { |
||||
logger.debug("Using new Session for TopLink interceptor"); |
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), new SessionHolder(session)); |
||||
} |
||||
try { |
||||
return methodInvocation.proceed(); |
||||
} |
||||
catch (TopLinkException ex) { |
||||
if (this.exceptionConversionEnabled) { |
||||
throw convertTopLinkAccessException(ex); |
||||
} |
||||
else { |
||||
throw ex; |
||||
} |
||||
} |
||||
finally { |
||||
if (existingTransaction) { |
||||
logger.debug("Not closing pre-bound TopLink Session after interceptor"); |
||||
} |
||||
else { |
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory()); |
||||
SessionFactoryUtils.releaseSession(session, getSessionFactory()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.DatabaseException; |
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException; |
||||
|
||||
/** |
||||
* TopLink-specific subclass of DataAccessException, for JDBC exceptions |
||||
* that TopLink rethrew. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @see SessionFactoryUtils#convertTopLinkAccessException |
||||
* @since 1.2 |
||||
*/ |
||||
public class TopLinkJdbcException extends UncategorizedDataAccessException { |
||||
|
||||
public TopLinkJdbcException(DatabaseException ex) { |
||||
super("JDBC exception on TopLink data access: " + ex.getMessage(), ex.getInternalException()); |
||||
} |
||||
|
||||
} |
||||
@ -1,703 +0,0 @@
@@ -1,703 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
import oracle.toplink.expressions.Expression; |
||||
import oracle.toplink.queryframework.Call; |
||||
import oracle.toplink.queryframework.DatabaseQuery; |
||||
import oracle.toplink.sessions.ObjectCopyingPolicy; |
||||
|
||||
import org.springframework.dao.DataAccessException; |
||||
|
||||
/** |
||||
* Interface that specifies a basic set of TopLink operations, |
||||
* implemented by {@link TopLinkTemplate}. Not often used, but a useful |
||||
* option to enhance testability, as it can easily be mocked or stubbed. |
||||
* |
||||
* <p>Defines <code>TopLinkTemplate</code>'s data access methods that |
||||
* mirror various TopLink {@link oracle.toplink.sessions.Session} / |
||||
* {@link oracle.toplink.sessions.UnitOfWork} methods. Users are |
||||
* strongly encouraged to read the TopLink javadocs for details |
||||
* on the semantics of those methods. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
*/ |
||||
public interface TopLinkOperations { |
||||
|
||||
/** |
||||
* Execute the action specified by the given action object within a |
||||
* TopLink Session. Application exceptions thrown by the action object |
||||
* get propagated to the caller (can only be unchecked). TopLink exceptions |
||||
* are transformed into appropriate DAO ones. Allows for returning a |
||||
* result object, i.e. a domain object or a collection of domain objects. |
||||
* <p>Note: Callback code is not supposed to handle transactions itself! |
||||
* Use an appropriate transaction manager like TopLinkTransactionManager. |
||||
* @param action callback object that specifies the TopLink action |
||||
* @return a result object returned by the action, or <code>null</code> |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see TopLinkTransactionManager |
||||
* @see org.springframework.dao |
||||
* @see org.springframework.transaction |
||||
* @see oracle.toplink.sessions.Session |
||||
*/ |
||||
Object execute(TopLinkCallback action) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute the specified action assuming that the result object is a |
||||
* Collection. This is a convenience method for executing TopLink queries |
||||
* within an action. |
||||
* @param action callback object that specifies the TopLink action |
||||
* @return a Collection result returned by the action, or <code>null</code> |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
*/ |
||||
List executeFind(TopLinkCallback action) throws DataAccessException; |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for executing generic queries
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Execute a given named query with the given arguments. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class that has the named query descriptor |
||||
* @param queryName the name of the query |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(String, Class) |
||||
*/ |
||||
Object executeNamedQuery(Class entityClass, String queryName) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute a given named query with the given arguments. |
||||
* @param entityClass the entity class that has the named query descriptor |
||||
* @param queryName the name of the query |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(String, Class) |
||||
*/ |
||||
Object executeNamedQuery(Class entityClass, String queryName, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute a given named query with the given arguments. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class that has the named query descriptor |
||||
* @param queryName the name of the query |
||||
* @param args the arguments for the query (can be <code>null</code>) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(String, Class, java.util.Vector) |
||||
*/ |
||||
Object executeNamedQuery(Class entityClass, String queryName, Object[] args) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute a given named query with the given arguments. |
||||
* @param entityClass the entity class that has the named query descriptor |
||||
* @param queryName the name of the query |
||||
* @param args the arguments for the query (can be <code>null</code>) |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(String, Class, java.util.Vector) |
||||
*/ |
||||
Object executeNamedQuery(Class entityClass, String queryName, Object[] args, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute the given query object with the given arguments. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param query the query object to execute (for example, |
||||
* a ReadObjectQuery or ReadAllQuery instance) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(oracle.toplink.queryframework.DatabaseQuery) |
||||
*/ |
||||
Object executeQuery(DatabaseQuery query) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute the given query object with the given arguments. |
||||
* @param query the query object to execute (for example, |
||||
* a ReadObjectQuery or ReadAllQuery instance) |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(oracle.toplink.queryframework.DatabaseQuery) |
||||
*/ |
||||
Object executeQuery(DatabaseQuery query, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute the given query object with the given arguments. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param query the query object to execute (for example, |
||||
* a ReadObjectQuery or ReadAllQuery instance) |
||||
* @param args the arguments for the query (can be <code>null</code>) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(oracle.toplink.queryframework.DatabaseQuery, java.util.Vector) |
||||
*/ |
||||
Object executeQuery(DatabaseQuery query, Object[] args) throws DataAccessException; |
||||
|
||||
/** |
||||
* Execute the given query object with the given arguments. |
||||
* @param query the query object to execute (for example, |
||||
* a ReadObjectQuery or ReadAllQuery instance) |
||||
* @param args the arguments for the query (can be <code>null</code>) |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the result object or list of result objects for the query |
||||
* (can be cast to the entity class or Collection/List, respectively) |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#executeQuery(oracle.toplink.queryframework.DatabaseQuery, java.util.Vector) |
||||
*/ |
||||
Object executeQuery(DatabaseQuery query, Object[] args, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for reading a specific set of objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Read all entity instances of the given class. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @return the list of entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class) |
||||
*/ |
||||
List readAll(Class entityClass) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read all entity instances of the given class. |
||||
* @param entityClass the entity class
|
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the list of entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class) |
||||
*/ |
||||
List readAll(Class entityClass, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read all entity instances of the given class that match the given expression. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param expression the TopLink expression to match, |
||||
* usually built through the TopLink ExpressionBuilder |
||||
* @return the list of matching entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.expressions.ExpressionBuilder |
||||
*/ |
||||
List readAll(Class entityClass, Expression expression) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read all entity instances of the given class that match the given expression. |
||||
* @param entityClass the entity class
|
||||
* @param expression the TopLink expression to match, |
||||
* usually built through the TopLink ExpressionBuilder |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the list of matching entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.expressions.ExpressionBuilder |
||||
*/ |
||||
List readAll(Class entityClass, Expression expression, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
/** |
||||
* Read all entity instances of the given class, as returned by the given call. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param call the TopLink Call object to apply (either a SQLCall or an EJBQLCall) |
||||
* @return the list of matching entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.queryframework.Call) |
||||
* @see oracle.toplink.queryframework.SQLCall |
||||
* @see oracle.toplink.queryframework.EJBQLCall |
||||
*/ |
||||
List readAll(Class entityClass, Call call) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read all entity instances of the given class, as returned by the given call. |
||||
* @param entityClass the entity class
|
||||
* @param call the TopLink Call object to apply (either a SQLCall or an EJBQLCall) |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the list of matching entity instances |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.queryframework.SQLCall |
||||
* @see oracle.toplink.queryframework.EJBQLCall |
||||
*/ |
||||
List readAll(Class entityClass, Call call, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read an entity instance of the given class that matches the given expression. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param expression the TopLink expression to match, |
||||
* usually built through the TopLink ExpressionBuilder |
||||
* @return the matching entity instance, or <code>null</code> if none found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.expressions.ExpressionBuilder |
||||
*/ |
||||
Object read(Class entityClass, Expression expression) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read an entity instance of the given class that matches the given expression. |
||||
* @param entityClass the entity class
|
||||
* @param expression the TopLink expression to match, |
||||
* usually built through the TopLink ExpressionBuilder |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return a matching entity instance, or <code>null</code> if none found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.expressions.ExpressionBuilder |
||||
*/ |
||||
Object read(Class entityClass, Expression expression, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
/** |
||||
* Read an entity instance of the given class, as returned by the given call. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param call the TopLink Call object to apply (either a SQLCall or an EJBQLCall) |
||||
* @return a matching entity instance, or <code>null</code> if none found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.queryframework.Call) |
||||
* @see oracle.toplink.queryframework.SQLCall |
||||
* @see oracle.toplink.queryframework.EJBQLCall |
||||
*/ |
||||
Object read(Class entityClass, Call call) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read an entity instance of the given class, as returned by the given call. |
||||
* @param entityClass the entity class
|
||||
* @param call the TopLink Call object to apply (either a SQLCall or an EJBQLCall) |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return a matching entity instance, or <code>null</code> if none found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#readAllObjects(Class, oracle.toplink.expressions.Expression) |
||||
* @see oracle.toplink.queryframework.SQLCall |
||||
* @see oracle.toplink.queryframework.EJBQLCall |
||||
*/ |
||||
Object read(Class entityClass, Call call, boolean enforceReadOnly) |
||||
throws DataAccessException; |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for reading an individual object by id
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given id, |
||||
* throwing an exception if not found. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param id the id of the desired object |
||||
* @return the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
*/ |
||||
Object readById(Class entityClass, Object id) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given id, |
||||
* throwing an exception if not found. |
||||
* @param entityClass the entity class
|
||||
* @param id the id of the desired object |
||||
* @return the entity instance |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
*/ |
||||
Object readById(Class entityClass, Object id, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given composite id, |
||||
* throwing an exception if not found. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param keys the composite id elements of the desired object |
||||
* @return the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
*/ |
||||
Object readById(Class entityClass, Object[] keys) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given composite id, |
||||
* throwing an exception if not found. |
||||
* @param entityClass the entity class
|
||||
* @param keys the composite id elements of the desired object |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
*/ |
||||
Object readById(Class entityClass, Object[] keys, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given id, |
||||
* throwing an exception if not found. A detached copy of the entity object |
||||
* will be returned, allowing for modifications outside the current transaction, |
||||
* with the changes to be merged into a later transaction. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param id the id of the desired object |
||||
* @return a copy of the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
Object readAndCopy(Class entityClass, Object id) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given id, |
||||
* throwing an exception if not found. A detached copy of the entity object |
||||
* will be returned, allowing for modifications outside the current transaction, |
||||
* with the changes to be merged into a later transaction. |
||||
* @param entityClass the entity class
|
||||
* @param id the id of the desired object |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return a copy of the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
Object readAndCopy(Class entityClass, Object id, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given composite id, |
||||
* throwing an exception if not found. A detached copy of the entity object |
||||
* will be returned, allowing for modifications outside the current transaction, |
||||
* with the changes to be merged into a later transaction. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entityClass the entity class
|
||||
* @param keys the composite id elements of the desired object |
||||
* @return a copy of the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
Object readAndCopy(Class entityClass, Object[] keys) throws DataAccessException; |
||||
|
||||
/** |
||||
* Read the entity instance of the given class with the given composite id, |
||||
* throwing an exception if not found. A detached copy of the entity object |
||||
* will be returned, allowing for modifications outside the current transaction, |
||||
* with the changes to be merged into a later transaction. |
||||
* @param entityClass the entity class
|
||||
* @param keys the composite id elements of the desired object |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return a copy of the entity instance |
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.queryframework.ReadObjectQuery#setSelectionKey(java.util.Vector) |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
Object readAndCopy(Class entityClass, Object[] keys, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for copying and refreshing objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Create a detached copy of the given entity object, |
||||
* using TopLink's default ObjectCopyingPolicy. |
||||
* @param entity the entity object to copy |
||||
* @return the copy of the entity object |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
Object copy(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Create a detached copy of the given entity object. |
||||
* @param entity the entity object to copy |
||||
* @param copyingPolicy the TopLink ObjectCopyingPolicy to apply |
||||
* @return the copy of the entity object |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object, oracle.toplink.sessions.ObjectCopyingPolicy) |
||||
*/ |
||||
Object copy(Object entity, ObjectCopyingPolicy copyingPolicy) throws DataAccessException; |
||||
|
||||
/** |
||||
* Create detached copies of all given entity objects, |
||||
* using TopLink's default ObjectCopyingPolicy. |
||||
* @param entities the entity objects to copy |
||||
* @return the copies of the entity objects |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
List copyAll(Collection entities) throws DataAccessException; |
||||
|
||||
/** |
||||
* Create detached copies of all given entity objects. |
||||
* @param entities the entity objects to copy |
||||
* @param copyingPolicy the TopLink ObjectCopyingPolicy to apply |
||||
* @return the copies of the entity objects |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#copyObject(Object) |
||||
*/ |
||||
List copyAll(Collection entities, ObjectCopyingPolicy copyingPolicy) throws DataAccessException; |
||||
|
||||
/** |
||||
* Refresh the given entity object, returning the refreshed object. |
||||
* <p>The returned object will only be different from the passed-in object |
||||
* if the passed-in object is not the currently registered version of |
||||
* the corresponding entity. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entity the entity object to refresh |
||||
* @return the refreshed version of the entity object |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#refreshObject(Object) |
||||
*/ |
||||
Object refresh(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Refresh the given entity object, returning the refreshed object. |
||||
* <p>The returned object will only be different from the passed-in object |
||||
* if the passed-in object is not the currently registered version of |
||||
* the corresponding entity. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entity the entity object to refresh |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the refreshed version of the entity object |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#refreshObject(Object) |
||||
*/ |
||||
Object refresh(Object entity, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
/** |
||||
* Refresh the given entity objects, returning the corresponding refreshed objects. |
||||
* <p>A returned object will only be different from the corresponding passed-in |
||||
* object if the passed-in object is not the currently registered version of |
||||
* the corresponding entity. |
||||
* <p>Retrieves read-write objects from the TopLink UnitOfWork in case of a |
||||
* non-read-only transaction, and read-only objects else. |
||||
* @param entities the entity objects to refresh |
||||
* @return the refreshed versions of the entity objects |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#refreshObject(Object) |
||||
*/ |
||||
List refreshAll(Collection entities) throws DataAccessException; |
||||
|
||||
/** |
||||
* Refresh the given entity objects, returning the corresponding refreshed objects. |
||||
* <p>A returned object will only be different from the corresponding passed-in |
||||
* object if the passed-in object is not the currently registered version of |
||||
* the corresponding entity. |
||||
* @param entities the entity objects to refresh |
||||
* @param enforceReadOnly whether to always retrieve read-only objects from |
||||
* the plain TopLink Session (else, read-write objects will be retrieved |
||||
* from the TopLink UnitOfWork in case of a non-read-only transaction) |
||||
* @return the refreshed versions of the entity objects |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.Session#refreshObject(Object) |
||||
*/ |
||||
List refreshAll(Collection entities, boolean enforceReadOnly) throws DataAccessException; |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for persisting and deleting objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Register the given (new or existing) entity with the current UnitOfWork. |
||||
* <p>The entity will be checked for existence, according to TopLink's |
||||
* configured existence checking policy. To avoid the (potentially costly) |
||||
* existence check, consider using the specific <code>registerNew</code> |
||||
* or <code>registerExisting</code> method. |
||||
* <b>Do not edit the passed-in object any further afterwards.</b> |
||||
* @param entity the entity to register |
||||
* @return the registered clone of the original object, |
||||
* which needs to be used for further editing |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#registerObject(Object) |
||||
* @see #registerNew(Object) |
||||
* @see #registerExisting(Object) |
||||
*/ |
||||
Object register(Object entity); |
||||
|
||||
/** |
||||
* Register all given entities with the current UnitOfWork. |
||||
* <b>Do not edit the passed-in objects any further afterwards.</b> |
||||
* @param entities the entities to register |
||||
* @return the registered clones of the original objects, |
||||
* which need to be used for further editing |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#registerAllObjects(java.util.Collection) |
||||
*/ |
||||
List registerAll(Collection entities); |
||||
|
||||
/** |
||||
* Register the given new entity with the current UnitOfWork. |
||||
* The passed-in object can be edited further afterwards. |
||||
* @param entity the new entity to register |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#registerNewObject(Object) |
||||
*/ |
||||
void registerNew(Object entity); |
||||
|
||||
/** |
||||
* Register the given existing entity with the current UnitOfWork. |
||||
* <b>Do not edit the passed-in object any further afterwards.</b> |
||||
* @param entity the existing entity to register |
||||
* @return the registered clone of the original object, |
||||
* which needs to be used for further editing |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#registerExistingObject(Object) |
||||
*/ |
||||
Object registerExisting(Object entity); |
||||
|
||||
/** |
||||
* Reassociate the given entity copy with the current UnitOfWork, |
||||
* using simple merging. |
||||
* <p>The given object will not be reassociated itself: instead, the state |
||||
* will be copied onto the persistent object with the same identifier. |
||||
* In case of a new entity, merge will copy to a registered object as well, |
||||
* but will also update the identifier of the passed-in object. |
||||
* @param entity the updated copy to merge |
||||
* @return the updated, registered persistent instance |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#mergeClone(Object) |
||||
*/ |
||||
Object merge(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Reassociate the given entity copy with the current UnitOfWork, |
||||
* using deep merging of all contained entities. |
||||
* <p>The given object will not be reassociated itself: instead, the state |
||||
* will be copied onto the persistent object with the same identifier. |
||||
* In case of a new entity, merge will register a copy as well, |
||||
* but will also update the identifier of the passed-in object. |
||||
* @param entity the updated copy to merge |
||||
* @return the updated, registered persistent instance |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#deepMergeClone(Object) |
||||
*/ |
||||
Object deepMerge(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Reassociate the given entity copy with the current UnitOfWork, |
||||
* using shallow merging of the entity instance. |
||||
* <p>The given object will not be reassociated itself: instead, the state |
||||
* will be copied onto the persistent object with the same identifier. |
||||
* In case of a new entity, merge will register a copy as well, |
||||
* but will also update the identifier of the passed-in object. |
||||
* @param entity the updated copy to merge |
||||
* @return the updated, registered persistent instance |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#shallowMergeClone(Object) |
||||
*/ |
||||
Object shallowMerge(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Reassociate the given entity copy with the current UnitOfWork, |
||||
* using merging with all references from this clone. |
||||
* <p>The given object will not be reassociated itself: instead, the state |
||||
* will be copied onto the persistent object with the same identifier. |
||||
* In case of a new entity, merge will register a copy as well, |
||||
* but will also update the identifier of the passed-in object. |
||||
* @param entity the updated copy to merge |
||||
* @return the updated, registered persistent instance |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#mergeCloneWithReferences(Object) |
||||
*/ |
||||
Object mergeWithReferences(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Delete the given entity. |
||||
* @param entity the entity to delete |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#deleteObject(Object) |
||||
*/ |
||||
void delete(Object entity) throws DataAccessException; |
||||
|
||||
/** |
||||
* Delete all given entities. |
||||
* @param entities the entities to delete |
||||
* @throws org.springframework.dao.DataAccessException in case of TopLink errors |
||||
* @see oracle.toplink.sessions.UnitOfWork#deleteAllObjects(java.util.Collection) |
||||
*/ |
||||
void deleteAll(Collection entities) throws DataAccessException; |
||||
|
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.OptimisticLockException; |
||||
|
||||
import org.springframework.orm.ObjectOptimisticLockingFailureException; |
||||
|
||||
/** |
||||
* TopLink-specific subclass of ObjectOptimisticLockingFailureException. |
||||
* Converts TopLink's OptimisticLockException. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
*/ |
||||
public class TopLinkOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException { |
||||
|
||||
public TopLinkOptimisticLockingFailureException(OptimisticLockException ex) { |
||||
super(ex.getObject() != null ? ex.getObject().getClass() : null, null, ex.getMessage(), ex); |
||||
} |
||||
|
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2006 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.QueryException; |
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException; |
||||
|
||||
/** |
||||
* TopLink-specific subclass of InvalidDataAccessResourceUsageException, |
||||
* thrown on invalid TopLink query syntax or behavior. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
*/ |
||||
public class TopLinkQueryException extends InvalidDataAccessResourceUsageException { |
||||
|
||||
public TopLinkQueryException(QueryException ex) { |
||||
super(ex.getMessage(), ex); |
||||
} |
||||
|
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException; |
||||
|
||||
/** |
||||
* TopLink-specific subclass of UncategorizedDataAccessException, |
||||
* for TopLink system errors that do not match any concrete |
||||
* <code>org.springframework.dao</code> exceptions. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see SessionFactoryUtils#convertTopLinkAccessException |
||||
*/ |
||||
public class TopLinkSystemException extends UncategorizedDataAccessException { |
||||
|
||||
public TopLinkSystemException(TopLinkException ex) { |
||||
super(ex.getMessage(), ex); |
||||
} |
||||
|
||||
} |
||||
@ -1,534 +0,0 @@
@@ -1,534 +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.toplink; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Vector; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.expressions.Expression; |
||||
import oracle.toplink.queryframework.Call; |
||||
import oracle.toplink.queryframework.DatabaseQuery; |
||||
import oracle.toplink.queryframework.ReadObjectQuery; |
||||
import oracle.toplink.sessions.ObjectCopyingPolicy; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.sessions.UnitOfWork; |
||||
|
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.dao.InvalidDataAccessApiUsageException; |
||||
import org.springframework.orm.ObjectRetrievalFailureException; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Helper class that simplifies TopLink data access code, and converts |
||||
* TopLinkExceptions into unchecked DataAccessExceptions, following the |
||||
* <code>org.springframework.dao</code> exception hierarchy. |
||||
* |
||||
* <p>The central method is <code>execute</code>, supporting TopLink access code |
||||
* implementing the {@link TopLinkCallback} interface. It provides TopLink Session |
||||
* handling such that neither the TopLinkCallback implementation nor the calling |
||||
* code needs to explicitly care about retrieving/closing TopLink Sessions, |
||||
* or handling Session lifecycle exceptions. For typical single step actions, |
||||
* there are various convenience methods (read, readAll, merge, delete, etc). |
||||
* |
||||
* <p>Can be used within a service implementation via direct instantiation |
||||
* with a SessionFactory reference, or get prepared in an application context |
||||
* and given to services as bean reference. Note: The SessionFactory should |
||||
* always be configured as bean in the application context, in the first case |
||||
* given to the service directly, in the second case to the prepared template. |
||||
* |
||||
* <p>This class can be considered as direct alternative to working with the raw |
||||
* TopLink Session API (through <code>SessionFactoryUtils.getSession()</code>). |
||||
* The major advantage is its automatic conversion to DataAccessExceptions, the |
||||
* major disadvantage that no checked application exceptions can get thrown from |
||||
* within data access code. Corresponding checks and the actual throwing of such |
||||
* exceptions can often be deferred to after callback execution, though. |
||||
* |
||||
* <p>{@link LocalSessionFactoryBean} is the preferred way of obtaining a reference |
||||
* to a specific TopLink SessionFactory. It will usually be configured to |
||||
* create ClientSessions for a ServerSession held by it, allowing for seamless |
||||
* multi-threaded execution. The Spring application context will manage its lifecycle, |
||||
* initializing and shutting down the factory as part of the application. |
||||
* |
||||
* <p>Thanks to Slavik Markovich for implementing the initial TopLink support prototype! |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a> |
||||
* @since 1.2 |
||||
* @see #setSessionFactory |
||||
* @see TopLinkCallback |
||||
* @see oracle.toplink.sessions.Session |
||||
* @see TopLinkInterceptor |
||||
* @see LocalSessionFactoryBean |
||||
* @see TopLinkTransactionManager |
||||
* @see org.springframework.transaction.jta.JtaTransactionManager |
||||
*/ |
||||
public class TopLinkTemplate extends TopLinkAccessor implements TopLinkOperations { |
||||
|
||||
private boolean allowCreate = true; |
||||
|
||||
|
||||
/** |
||||
* Create a new TopLinkTemplate instance. |
||||
*/ |
||||
public TopLinkTemplate() { |
||||
} |
||||
|
||||
/** |
||||
* Create a new TopLinkTemplate instance. |
||||
*/ |
||||
public TopLinkTemplate(SessionFactory sessionFactory) { |
||||
setSessionFactory(sessionFactory); |
||||
afterPropertiesSet(); |
||||
} |
||||
|
||||
/** |
||||
* Create a new TopLinkTemplate instance. |
||||
* @param allowCreate if a new Session should be created if no thread-bound found |
||||
*/ |
||||
public TopLinkTemplate(SessionFactory sessionFactory, boolean allowCreate) { |
||||
setSessionFactory(sessionFactory); |
||||
setAllowCreate(allowCreate); |
||||
afterPropertiesSet(); |
||||
} |
||||
|
||||
/** |
||||
* Set if a new Session should be created when no transactional Session |
||||
* can be found for the current thread. |
||||
* <p>TopLinkTemplate is aware of a corresponding Session bound to the |
||||
* current thread, for example when using TopLinkTransactionManager. |
||||
* If allowCreate is true, a new non-transactional Session will be created |
||||
* if none found, which needs to be closed at the end of the operation. |
||||
* If false, an IllegalStateException will get thrown in this case. |
||||
* @see SessionFactoryUtils#getSession(SessionFactory, boolean) |
||||
*/ |
||||
public void setAllowCreate(boolean allowCreate) { |
||||
this.allowCreate = allowCreate; |
||||
} |
||||
|
||||
/** |
||||
* Return if a new Session should be created if no thread-bound found. |
||||
*/ |
||||
public boolean isAllowCreate() { |
||||
return this.allowCreate; |
||||
} |
||||
|
||||
|
||||
public Object execute(TopLinkCallback action) throws DataAccessException { |
||||
Assert.notNull(action, "Callback object must not be null"); |
||||
|
||||
Session session = SessionFactoryUtils.getSession(getSessionFactory(), this.allowCreate); |
||||
try { |
||||
return action.doInTopLink(session); |
||||
} |
||||
catch (TopLinkException ex) { |
||||
throw convertTopLinkAccessException(ex); |
||||
} |
||||
catch (RuntimeException ex) { |
||||
// callback code threw application exception
|
||||
throw ex; |
||||
} |
||||
finally { |
||||
SessionFactoryUtils.releaseSession(session, getSessionFactory()); |
||||
} |
||||
} |
||||
|
||||
public List executeFind(TopLinkCallback action) throws DataAccessException { |
||||
Object result = execute(action); |
||||
if (result != null && !(result instanceof List)) { |
||||
throw new InvalidDataAccessApiUsageException( |
||||
"Result object returned from TopLinkCallback isn't a List: [" + result + "]"); |
||||
} |
||||
return (List) result; |
||||
} |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for executing generic queries
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object executeNamedQuery(Class entityClass, String queryName) throws DataAccessException { |
||||
return executeNamedQuery(entityClass, queryName, null, false); |
||||
} |
||||
|
||||
public Object executeNamedQuery(Class entityClass, String queryName, boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return executeNamedQuery(entityClass, queryName, null, enforceReadOnly); |
||||
} |
||||
|
||||
public Object executeNamedQuery(Class entityClass, String queryName, Object[] args) |
||||
throws DataAccessException { |
||||
|
||||
return executeNamedQuery(entityClass, queryName, args, false); |
||||
} |
||||
|
||||
public Object executeNamedQuery( |
||||
final Class entityClass, final String queryName, final Object[] args, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
if (args != null) { |
||||
return session.executeQuery(queryName, entityClass, new Vector(Arrays.asList(args))); |
||||
} |
||||
else { |
||||
return session.executeQuery(queryName, entityClass, new Vector()); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object executeQuery(DatabaseQuery query) throws DataAccessException { |
||||
return executeQuery(query, null, false); |
||||
} |
||||
|
||||
public Object executeQuery(DatabaseQuery query, boolean enforceReadOnly) throws DataAccessException { |
||||
return executeQuery(query, null, enforceReadOnly); |
||||
} |
||||
|
||||
public Object executeQuery(DatabaseQuery query, Object[] args) throws DataAccessException { |
||||
return executeQuery(query, args, false); |
||||
} |
||||
|
||||
public Object executeQuery(final DatabaseQuery query, final Object[] args, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
if (args != null) { |
||||
return session.executeQuery(query, new Vector(Arrays.asList(args))); |
||||
} |
||||
else { |
||||
return session.executeQuery(query); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for reading a specific set of objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public List readAll(Class entityClass) throws DataAccessException { |
||||
return readAll(entityClass, false); |
||||
} |
||||
|
||||
public List readAll(final Class entityClass, final boolean enforceReadOnly) throws DataAccessException { |
||||
return executeFind(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.readAllObjects(entityClass); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public List readAll(Class entityClass, Expression expression) throws DataAccessException { |
||||
return readAll(entityClass, expression, false); |
||||
} |
||||
|
||||
public List readAll(final Class entityClass, final Expression expression, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return executeFind(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.readAllObjects(entityClass, expression); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public List readAll(Class entityClass, Call call) throws DataAccessException { |
||||
return readAll(entityClass, call, false); |
||||
} |
||||
|
||||
public List readAll(final Class entityClass, final Call call, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return executeFind(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.readAllObjects(entityClass, call); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object read(Class entityClass, Expression expression) throws DataAccessException { |
||||
return read(entityClass, expression, false); |
||||
} |
||||
|
||||
public Object read(final Class entityClass, final Expression expression, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.readObject(entityClass, expression); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object read(Class entityClass, Call call) throws DataAccessException { |
||||
return read(entityClass, call, false); |
||||
} |
||||
|
||||
public Object read(final Class entityClass, final Call call, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
return execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.readObject(entityClass, call); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for reading an individual object by id
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object readById(Class entityClass, Object id) throws DataAccessException { |
||||
return readById(entityClass, id, false); |
||||
} |
||||
|
||||
public Object readById(Class entityClass, Object id, boolean enforceReadOnly) throws DataAccessException { |
||||
return readById(entityClass, new Object[] {id}, enforceReadOnly); |
||||
} |
||||
|
||||
public Object readById(Class entityClass, Object[] keys) throws DataAccessException { |
||||
return readById(entityClass, keys, false); |
||||
} |
||||
|
||||
public Object readById(final Class entityClass, final Object[] keys, final boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
Assert.isTrue(keys != null && keys.length > 0, "Non-empty keys or id is required"); |
||||
|
||||
ReadObjectQuery query = new ReadObjectQuery(entityClass); |
||||
query.setSelectionKey(new Vector(Arrays.asList(keys))); |
||||
Object result = executeQuery(query, enforceReadOnly); |
||||
|
||||
if (result == null) { |
||||
Object identifier = (keys.length == 1 ? keys[0] : StringUtils.arrayToCommaDelimitedString(keys)); |
||||
throw new ObjectRetrievalFailureException(entityClass, identifier); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public Object readAndCopy(Class entityClass, Object id) throws DataAccessException { |
||||
return readAndCopy(entityClass, id, false); |
||||
} |
||||
|
||||
public Object readAndCopy(Class entityClass, Object id, boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
Object entity = readById(entityClass, id, enforceReadOnly); |
||||
return copy(entity); |
||||
} |
||||
|
||||
public Object readAndCopy(Class entityClass, Object[] keys) throws DataAccessException { |
||||
return readAndCopy(entityClass, keys, false); |
||||
} |
||||
|
||||
public Object readAndCopy(Class entityClass, Object[] keys, boolean enforceReadOnly) |
||||
throws DataAccessException { |
||||
|
||||
Object entity = readById(entityClass, keys, enforceReadOnly); |
||||
return copy(entity); |
||||
} |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for copying and refreshing objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object copy(Object entity) throws DataAccessException { |
||||
ObjectCopyingPolicy copyingPolicy = new ObjectCopyingPolicy(); |
||||
copyingPolicy.cascadeAllParts(); |
||||
copyingPolicy.setShouldResetPrimaryKey(false); |
||||
return copy(entity, copyingPolicy); |
||||
} |
||||
|
||||
public Object copy(final Object entity, final ObjectCopyingPolicy copyingPolicy) |
||||
throws DataAccessException { |
||||
|
||||
return execute(new TopLinkCallback() { |
||||
public Object doInTopLink(Session session) throws TopLinkException { |
||||
return session.copyObject(entity, copyingPolicy); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public List copyAll(Collection entities) throws DataAccessException { |
||||
ObjectCopyingPolicy copyingPolicy = new ObjectCopyingPolicy(); |
||||
copyingPolicy.cascadeAllParts(); |
||||
copyingPolicy.setShouldResetPrimaryKey(false); |
||||
return copyAll(entities, copyingPolicy); |
||||
} |
||||
|
||||
public List copyAll(final Collection entities, final ObjectCopyingPolicy copyingPolicy) |
||||
throws DataAccessException { |
||||
|
||||
return (List) execute(new TopLinkCallback() { |
||||
public Object doInTopLink(Session session) throws TopLinkException { |
||||
List result = new ArrayList(entities.size()); |
||||
for (Iterator it = entities.iterator(); it.hasNext();) { |
||||
Object entity = it.next(); |
||||
result.add(session.copyObject(entity, copyingPolicy)); |
||||
} |
||||
return result; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object refresh(Object entity) throws DataAccessException { |
||||
return refresh(entity, false); |
||||
} |
||||
|
||||
public Object refresh(final Object entity, final boolean enforceReadOnly) throws DataAccessException { |
||||
return execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
return session.refreshObject(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public List refreshAll(Collection entities) throws DataAccessException { |
||||
return refreshAll(entities, false); |
||||
} |
||||
|
||||
public List refreshAll(final Collection entities, final boolean enforceReadOnly) throws DataAccessException { |
||||
return (List) execute(new SessionReadCallback(enforceReadOnly) { |
||||
@Override |
||||
protected Object readFromSession(Session session) throws TopLinkException { |
||||
List result = new ArrayList(entities.size()); |
||||
for (Iterator it = entities.iterator(); it.hasNext();) { |
||||
Object entity = it.next(); |
||||
result.add(session.refreshObject(entity)); |
||||
} |
||||
return result; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for persisting and deleting objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object register(final Object entity) { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.registerObject(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public List registerAll(final Collection entities) { |
||||
return (List) execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.registerAllObjects(entities); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void registerNew(final Object entity) { |
||||
execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.registerNewObject(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object registerExisting(final Object entity) { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.registerExistingObject(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object merge(final Object entity) throws DataAccessException { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.mergeClone(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object deepMerge(final Object entity) throws DataAccessException { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.deepMergeClone(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object shallowMerge(final Object entity) throws DataAccessException { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.shallowMergeClone(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public Object mergeWithReferences(final Object entity) throws DataAccessException { |
||||
return execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.mergeCloneWithReferences(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void delete(final Object entity) throws DataAccessException { |
||||
execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
return unitOfWork.deleteObject(entity); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void deleteAll(final Collection entities) throws DataAccessException { |
||||
execute(new UnitOfWorkCallback() { |
||||
@Override |
||||
protected Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException { |
||||
unitOfWork.deleteAllObjects(entities); |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
@ -1,489 +0,0 @@
@@ -1,489 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2008 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.toplink; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import oracle.toplink.exceptions.DatabaseException; |
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.internal.databaseaccess.Accessor; |
||||
import oracle.toplink.internal.databaseaccess.DatabaseAccessor; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.jdbc.datasource.ConnectionHolder; |
||||
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport; |
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; |
||||
import org.springframework.jdbc.support.SQLExceptionTranslator; |
||||
import org.springframework.transaction.CannotCreateTransactionException; |
||||
import org.springframework.transaction.TransactionDefinition; |
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager; |
||||
import org.springframework.transaction.support.DefaultTransactionStatus; |
||||
import org.springframework.transaction.support.ResourceTransactionManager; |
||||
import org.springframework.transaction.support.TransactionSynchronizationManager; |
||||
|
||||
/** |
||||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation |
||||
* for a single TopLink {@link SessionFactory}. Binds a TopLink Session from the |
||||
* specified factory to the thread, potentially allowing for one thread-bound Session |
||||
* per factory. {@link SessionFactoryUtils} and {@link TopLinkTemplate} are aware |
||||
* of thread-bound Sessions and participate in such transactions automatically. |
||||
* Using either of those or going through <code>Session.getActiveUnitOfWork()</code> is |
||||
* required for TopLink access code supporting this transaction handling mechanism. |
||||
* |
||||
* <p>This transaction manager is appropriate for applications that use a single |
||||
* TopLink SessionFactory 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 TopLink with an appropriate external transaction |
||||
* controller 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), but only for transactions |
||||
* that are <i>not</i> marked as read-only. This allows for mixing services which |
||||
* access TopLink and services which use plain JDBC (without being aware of TopLink)! |
||||
* 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 TopLink |
||||
* SessionFactory. |
||||
* |
||||
* <p>On JDBC 3.0, 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 TopLink PersistenceManager and its cached objects. |
||||
* You can manually set the flag to "true" if you want to use nested transactions |
||||
* for JDBC access code which participates in TopLink transactions (provided that |
||||
* your JDBC driver supports Savepoints). <i>Note that TopLink itself does not |
||||
* support nested transactions! Hence, do not expect TopLink access code to |
||||
* semantically participate in a nested transaction.</i> |
||||
* |
||||
* <p>Thanks to Slavik Markovich for implementing the initial TopLink support prototype! |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a> |
||||
* @since 1.2 |
||||
* @see #setSessionFactory |
||||
* @see #setDataSource |
||||
* @see LocalSessionFactoryBean |
||||
* @see SessionFactoryUtils#getSession |
||||
* @see SessionFactoryUtils#releaseSession |
||||
* @see TopLinkTemplate |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection |
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#applyTransactionTimeout |
||||
* @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 |
||||
*/ |
||||
public class TopLinkTransactionManager extends AbstractPlatformTransactionManager |
||||
implements ResourceTransactionManager, InitializingBean { |
||||
|
||||
private SessionFactory sessionFactory; |
||||
|
||||
private DataSource dataSource; |
||||
|
||||
private boolean lazyDatabaseTransaction = false; |
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator; |
||||
|
||||
|
||||
/** |
||||
* Create a new TopLinkTransactionManager instance. |
||||
* A SessionFactory has to be specified to be able to use it. |
||||
* @see #setSessionFactory |
||||
*/ |
||||
public TopLinkTransactionManager() { |
||||
} |
||||
|
||||
/** |
||||
* Create a new TopLinkTransactionManager instance. |
||||
* @param sessionFactory the TopLink SessionFactory to manage transactions for |
||||
*/ |
||||
public TopLinkTransactionManager(SessionFactory sessionFactory) { |
||||
this.sessionFactory = sessionFactory; |
||||
afterPropertiesSet(); |
||||
} |
||||
|
||||
/** |
||||
* Set the the TopLink SessionFactory to manage transactions for. |
||||
* This will usually be a ServerSessionFactory. |
||||
* <p>The passed-in SessionFactory will be asked for a plain Session |
||||
* in case of a read-only transaction (where no active UnitOfWork is |
||||
* supposed to be available), and for a managed Session else (with an |
||||
* active UnitOfWork that will be committed by this transaction manager). |
||||
* @see ServerSessionFactory |
||||
* @see SessionFactory#createSession() |
||||
* @see SessionFactory#createManagedClientSession() |
||||
*/ |
||||
public void setSessionFactory(SessionFactory sessionFactory) { |
||||
this.sessionFactory = sessionFactory; |
||||
} |
||||
|
||||
/** |
||||
* Return the SessionFactory that this instance should manage transactions for. |
||||
*/ |
||||
public SessionFactory getSessionFactory() { |
||||
return this.sessionFactory; |
||||
} |
||||
|
||||
/** |
||||
* Set the JDBC DataSource that this instance should manage transactions for. |
||||
* The DataSource should match the one used by the TopLink SessionFactory: |
||||
* for example, you could specify the same JNDI DataSource for both. |
||||
* <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 TopLink Session. |
||||
* <b>This will only happen for transactions that are <i>not</i> marked |
||||
* as read-only.</b> TopLink does not support database transactions for pure |
||||
* read-only operations on a Session (that is, without a UnitOfWork). |
||||
* <p>Note that you need to use a TopLink Session with a DatabaseAccessor |
||||
* to allow for exposing TopLink transactions as JDBC transactions. This is |
||||
* the case of all standard TopLink configurations. |
||||
* <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 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 lazily start a database transaction within a TopLink |
||||
* transaction. |
||||
* <p>By default, database transactions are started early. This allows |
||||
* for reusing the same JDBC Connection throughout an entire transaction, |
||||
* including read operations, and also for exposing TopLink transactions |
||||
* to JDBC access code (working on the same DataSource). |
||||
* <p>It is only recommended to switch this flag to "true" when no JDBC access |
||||
* code is involved in any of the transactions, and when it is acceptable to |
||||
* perform read operations outside of the transactional JDBC Connection. |
||||
* @see #setDataSource(javax.sql.DataSource) |
||||
* @see oracle.toplink.sessions.UnitOfWork#beginEarlyTransaction() |
||||
*/ |
||||
public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) { |
||||
this.lazyDatabaseTransaction = lazyDatabaseTransaction; |
||||
} |
||||
|
||||
/** |
||||
* Return whether to lazily start a database transaction within a TopLink |
||||
* transaction. |
||||
*/ |
||||
public boolean isLazyDatabaseTransaction() { |
||||
return this.lazyDatabaseTransaction; |
||||
} |
||||
|
||||
/** |
||||
* Set the JDBC exception translator for this transaction manager. |
||||
* <p>Applied to any SQLException root cause of a TopLink DatabaseException |
||||
* that is thrown on commit. The default is to rely on TopLink's native |
||||
* exception translation. |
||||
* @param jdbcExceptionTranslator the exception translator |
||||
* @see oracle.toplink.exceptions.DatabaseException |
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator |
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator |
||||
* @see #setDataSource(javax.sql.DataSource) |
||||
*/ |
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) { |
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator; |
||||
} |
||||
|
||||
/** |
||||
* Return the JDBC exception translator for this transaction manager, if any. |
||||
*/ |
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() { |
||||
return this.jdbcExceptionTranslator; |
||||
} |
||||
|
||||
public void afterPropertiesSet() { |
||||
if (getSessionFactory() == null) { |
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required"); |
||||
} |
||||
} |
||||
|
||||
|
||||
public Object getResourceFactory() { |
||||
return getSessionFactory(); |
||||
} |
||||
|
||||
@Override |
||||
protected Object doGetTransaction() { |
||||
TopLinkTransactionObject txObject = new TopLinkTransactionObject(); |
||||
SessionHolder sessionHolder = (SessionHolder) |
||||
TransactionSynchronizationManager.getResource(this.sessionFactory); |
||||
txObject.setSessionHolder(sessionHolder); |
||||
return txObject; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isExistingTransaction(Object transaction) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) transaction; |
||||
return (txObject.getSessionHolder() != null); |
||||
} |
||||
|
||||
@Override |
||||
protected void doBegin(Object transaction, TransactionDefinition definition) { |
||||
Session session = null; |
||||
|
||||
try { |
||||
if (!definition.isReadOnly()) { |
||||
logger.debug("Creating managed TopLink Session with active UnitOfWork for read-write transaction"); |
||||
session = getSessionFactory().createManagedClientSession(); |
||||
} |
||||
else { |
||||
logger.debug("Creating plain TopLink Session without active UnitOfWork for read-only transaction"); |
||||
session = getSessionFactory().createSession(); |
||||
} |
||||
|
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Opened new session [" + session + "] for TopLink transaction"); |
||||
} |
||||
|
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) transaction; |
||||
txObject.setSessionHolder(new SessionHolder(session)); |
||||
txObject.getSessionHolder().setSynchronizedWithTransaction(true); |
||||
|
||||
// Register transaction timeout.
|
||||
int timeout = determineTimeout(definition); |
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { |
||||
txObject.getSessionHolder().setTimeoutInSeconds(timeout); |
||||
} |
||||
|
||||
// Enforce early database transaction for TopLink read-write transaction,
|
||||
// unless we are explicitly told to use lazy transactions.
|
||||
if (!definition.isReadOnly() && !isLazyDatabaseTransaction()) { |
||||
session.getActiveUnitOfWork().beginEarlyTransaction(); |
||||
} |
||||
|
||||
// Register the TopLink Session's JDBC Connection for the DataSource, if set.
|
||||
if (getDataSource() != null) { |
||||
Session mostSpecificSession = (!definition.isReadOnly() ? session.getActiveUnitOfWork() : session); |
||||
Connection con = getJdbcConnection(mostSpecificSession); |
||||
if (con != null) { |
||||
ConnectionHolder conHolder = new ConnectionHolder(con); |
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { |
||||
conHolder.setTimeoutInSeconds(timeout); |
||||
} |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Exposing TopLink transaction as JDBC transaction [" + con + "]"); |
||||
} |
||||
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); |
||||
txObject.setConnectionHolder(conHolder); |
||||
} |
||||
else { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Not exposing TopLink transaction [" + session + |
||||
"] as JDBC transaction because no JDBC Connection could be retrieved from it"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Bind the session holder to the thread.
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder()); |
||||
} |
||||
|
||||
catch (Exception ex) { |
||||
SessionFactoryUtils.releaseSession(session, getSessionFactory()); |
||||
throw new CannotCreateTransactionException("Could not open TopLink Session for transaction", ex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Extract the underlying JDBC Connection from the given TopLink Session. |
||||
* <p>Default implementation casts to <code>oracle.toplink.publicinterface.Session</code> |
||||
* and fetches the Connection from the DatabaseAccessor exposed there. |
||||
* @param session the current TopLink Session |
||||
* @return the underlying JDBC Connection, or <code>null</code> if none found |
||||
* @see oracle.toplink.publicinterface.Session#getAccessor() |
||||
* @see oracle.toplink.internal.databaseaccess.DatabaseAccessor#getConnection() |
||||
*/ |
||||
protected Connection getJdbcConnection(Session session) { |
||||
if (!(session instanceof oracle.toplink.publicinterface.Session)) { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("TopLink Session [" + session + |
||||
"] does not derive from [oracle.toplink.publicinterface.Session]"); |
||||
} |
||||
return null; |
||||
} |
||||
Accessor accessor = ((oracle.toplink.publicinterface.Session) session).getAccessor(); |
||||
if (!(accessor instanceof DatabaseAccessor)) { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("TopLink Accessor [" + accessor + |
||||
"] does not derive from [oracle.toplink.internal.databaseaccess.DatabaseAccessor]"); |
||||
} |
||||
return null; |
||||
} |
||||
return ((DatabaseAccessor) accessor).getConnection(); |
||||
} |
||||
|
||||
@Override |
||||
protected Object doSuspend(Object transaction) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) transaction; |
||||
txObject.setSessionHolder(null); |
||||
return TransactionSynchronizationManager.unbindResource(getSessionFactory()); |
||||
} |
||||
|
||||
@Override |
||||
protected void doResume(Object transaction, Object suspendedResources) { |
||||
SessionHolder sessionHolder = (SessionHolder) suspendedResources; |
||||
if (TransactionSynchronizationManager.hasResource(getSessionFactory())) { |
||||
// From non-transactional code running in active transaction synchronization
|
||||
// -> can be safely removed, will be closed on transaction completion.
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory()); |
||||
} |
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), sessionHolder); |
||||
} |
||||
|
||||
@Override |
||||
protected void doCommit(DefaultTransactionStatus status) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) status.getTransaction(); |
||||
if (status.isDebug()) { |
||||
logger.debug("Committing TopLink transaction on session [" + |
||||
txObject.getSessionHolder().getSession() + "]"); |
||||
} |
||||
try { |
||||
if (!status.isReadOnly()) { |
||||
txObject.getSessionHolder().getSession().getActiveUnitOfWork().commit(); |
||||
} |
||||
txObject.getSessionHolder().clear(); |
||||
} |
||||
catch (TopLinkException ex) { |
||||
throw convertTopLinkAccessException(ex); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void doRollback(DefaultTransactionStatus status) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) status.getTransaction(); |
||||
if (status.isDebug()) { |
||||
logger.debug("Not committing TopLink transaction on session [" + |
||||
txObject.getSessionHolder().getSession() + "]"); |
||||
} |
||||
txObject.getSessionHolder().clear(); |
||||
} |
||||
|
||||
@Override |
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) status.getTransaction(); |
||||
if (status.isDebug()) { |
||||
logger.debug("Setting TopLink transaction on session [" + |
||||
txObject.getSessionHolder().getSession() + "] rollback-only"); |
||||
} |
||||
txObject.getSessionHolder().setRollbackOnly(); |
||||
} |
||||
|
||||
@Override |
||||
protected void doCleanupAfterCompletion(Object transaction) { |
||||
TopLinkTransactionObject txObject = (TopLinkTransactionObject) transaction; |
||||
|
||||
// Remove the session holder from the thread.
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory()); |
||||
|
||||
// Remove the JDBC connection holder from the thread, if exposed.
|
||||
if (txObject.hasConnectionHolder()) { |
||||
TransactionSynchronizationManager.unbindResource(getDataSource()); |
||||
} |
||||
|
||||
Session session = txObject.getSessionHolder().getSession(); |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Releasing TopLink Session [" + session + "] after transaction"); |
||||
} |
||||
try { |
||||
session.release(); |
||||
} |
||||
catch (Throwable ex) { |
||||
// just log it, to keep a transaction-related exception
|
||||
logger.debug("Could not release TopLink Session after transaction", ex); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Convert the given TopLinkException to an appropriate exception from the |
||||
* <code>org.springframework.dao</code> hierarchy. |
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a |
||||
* TopLink DatabaseException, else rely on TopLink's default translation. |
||||
* @param ex TopLinkException that occured |
||||
* @return a corresponding DataAccessException |
||||
* @see SessionFactoryUtils#convertTopLinkAccessException |
||||
* @see #setJdbcExceptionTranslator |
||||
*/ |
||||
protected DataAccessException convertTopLinkAccessException(TopLinkException ex) { |
||||
if (getJdbcExceptionTranslator() != null && ex instanceof DatabaseException) { |
||||
Throwable internalEx = ex.getInternalException(); |
||||
// Should always be a SQLException inside a DatabaseException.
|
||||
if (internalEx instanceof SQLException) { |
||||
return getJdbcExceptionTranslator().translate( |
||||
"TopLink commit: " + ex.getMessage(), null, (SQLException) internalEx); |
||||
} |
||||
} |
||||
return SessionFactoryUtils.convertTopLinkAccessException(ex); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* TopLink transaction object, representing a SessionHolder. |
||||
* Used as transaction object by TopLinkTransactionManager. |
||||
*/ |
||||
private static class TopLinkTransactionObject extends JdbcTransactionObjectSupport { |
||||
|
||||
private SessionHolder sessionHolder; |
||||
|
||||
public void setSessionHolder(SessionHolder sessionHolder) { |
||||
this.sessionHolder = sessionHolder; |
||||
} |
||||
|
||||
public SessionHolder getSessionHolder() { |
||||
return this.sessionHolder; |
||||
} |
||||
|
||||
public boolean isRollbackOnly() { |
||||
return getSessionHolder().isRollbackOnly(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.sessions.UnitOfWork; |
||||
|
||||
/** |
||||
* Convenient abstract implementation of the TopLinkCallback interface, |
||||
* exposing a UnitOfWork to perform write operations on. |
||||
* |
||||
* <p>The exposed UnitOfWork will either be be the active UnitOfWork of |
||||
* the current transaction, if any, or a temporarily acquired UnitOfWork |
||||
* that will be committed at the end of the operation. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see #doInUnitOfWork(oracle.toplink.sessions.UnitOfWork) |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
public abstract class UnitOfWorkCallback implements TopLinkCallback { |
||||
|
||||
/** |
||||
* Determines the UnitOfWork to work on (either the active UnitOfWork or a |
||||
* temporarily acquired UnitOfWork) and delegates to <code>doInUnitOfWork</code>. |
||||
* @see #doInUnitOfWork(oracle.toplink.sessions.UnitOfWork) |
||||
*/ |
||||
public final Object doInTopLink(Session session) throws TopLinkException { |
||||
// Fetch active UnitOfWork or acquire temporary UnitOfWork.
|
||||
UnitOfWork unitOfWork = session.getActiveUnitOfWork(); |
||||
boolean newUnitOfWork = false; |
||||
if (unitOfWork == null) { |
||||
unitOfWork = session.acquireUnitOfWork(); |
||||
newUnitOfWork = true; |
||||
} |
||||
|
||||
// Perform callback operation, committing the UnitOfWork unless
|
||||
// it is the active UnitOfWork of an externally managed transaction.
|
||||
try { |
||||
Object result = doInUnitOfWork(unitOfWork); |
||||
if (newUnitOfWork) { |
||||
unitOfWork.commit(); |
||||
} |
||||
return result; |
||||
} |
||||
finally { |
||||
if (newUnitOfWork) { |
||||
unitOfWork.release(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Called with a UnitOfWork to work on, either the active UnitOfWork or a |
||||
* temporarily acquired UnitOfWork (as determined by the transaction status). |
||||
* @param unitOfWork the TopLink UnitOfWork to perform write operations on |
||||
* @return a result object, or <code>null</code> if none |
||||
* @throws TopLinkException in case of TopLink errors |
||||
*/ |
||||
protected abstract Object doInUnitOfWork(UnitOfWork unitOfWork) throws TopLinkException; |
||||
|
||||
} |
||||
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Package providing integration of |
||||
<a href="http://www.oracle.com/technology/products/ias/toplink">Oracle TopLink</a> |
||||
with Spring concepts. |
||||
|
||||
<p>Contains SessionFactory helper classes, a template plus callback |
||||
for TopLink access, and an implementation of Spring's transaction SPI |
||||
for local TopLink transactions. |
||||
|
||||
</body> |
||||
</html> |
||||
@ -1,218 +0,0 @@
@@ -1,218 +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.toplink.support; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
import oracle.toplink.internal.databaseaccess.Accessor; |
||||
import oracle.toplink.logging.AbstractSessionLog; |
||||
import oracle.toplink.logging.SessionLogEntry; |
||||
import oracle.toplink.publicinterface.Session; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
/** |
||||
* TopLink 10.1.3+ SessionLog implementation that logs through Commons Logging. |
||||
* |
||||
* <p>The namespace used is "oracle.toplink.xxx", with the latter part being |
||||
* the TopLink log category ("sql"/"transaction"/etc). In case of no category |
||||
* given, "session" will be used as default. This allows for fine-grained |
||||
* filtering of log messages, for example through Log4J configuration. |
||||
* |
||||
* <p>Maps TopLink's SEVERE level to CL ERROR, TopLink's WARNING to CL WARN, |
||||
* TopLink's INFO to CL INFO, TopLink's CONFIG/FINE/FINER to CL DEBUG, |
||||
* and TopLink's FINEST to CL TRACE. This results in common CL log behavior: |
||||
* INFO logging only at startup; operation logging at DEBUG level. Debug logging |
||||
* can be further filtered according to categories: for example, activate Log4J |
||||
* DEBUG logging for category "oracle.toplink.sql" to see the generated SQL. |
||||
* |
||||
* <p><b>Note:</b> This implementation will only work on TopLink 10.1.3 or higher, |
||||
* as it is built against TopLink's new SessionLog facilities in the |
||||
* <code>oracle.toplink.logging</code> package, supporting log categories. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see CommonsLoggingSessionLog904 |
||||
* @see oracle.toplink.logging.JavaLog |
||||
* @see org.springframework.orm.toplink.LocalSessionFactoryBean#setSessionLog |
||||
*/ |
||||
public class CommonsLoggingSessionLog extends AbstractSessionLog { |
||||
|
||||
public static final String NAMESPACE_PREFIX = "oracle.toplink."; |
||||
|
||||
public static final String DEFAULT_NAMESPACE = "session"; |
||||
|
||||
public static final String DEFAULT_SEPARATOR = "--"; |
||||
|
||||
|
||||
private static Method getSessionMethod; |
||||
|
||||
private static Method getExceptionMethod; |
||||
|
||||
static { |
||||
try { |
||||
getSessionMethod = SessionLogEntry.class.getMethod("getSession", new Class[0]); |
||||
} |
||||
catch (NoSuchMethodException ex) { |
||||
throw new IllegalStateException("Could not find method SessionLogEntry.getSession()"); |
||||
} |
||||
try { |
||||
getExceptionMethod = SessionLogEntry.class.getMethod("getException", new Class[0]); |
||||
} |
||||
catch (NoSuchMethodException ex) { |
||||
throw new IllegalStateException("Could not find method SessionLogEntry.getException()"); |
||||
} |
||||
} |
||||
|
||||
|
||||
private String separator = DEFAULT_SEPARATOR; |
||||
|
||||
|
||||
/** |
||||
* Specify the separator between TopLink's supplemental details |
||||
* (session, connection) and the log message itself. Default is "--". |
||||
*/ |
||||
public void setSeparator(String separator) { |
||||
this.separator = separator; |
||||
} |
||||
|
||||
/** |
||||
* Return the separator between TopLink's supplemental details |
||||
* (session, connection) and the log message itself. Default is "--". |
||||
*/ |
||||
public String getSeparator() { |
||||
return this.separator; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void log(SessionLogEntry entry) { |
||||
Log logger = LogFactory.getLog(getCategory(entry)); |
||||
switch (entry.getLevel()) { |
||||
case SEVERE: |
||||
if (logger.isErrorEnabled()) { |
||||
if (entry.hasException()) { |
||||
logger.error(getMessageString(entry), getException(entry)); |
||||
} |
||||
else { |
||||
logger.error(getMessageString(entry)); |
||||
} |
||||
} |
||||
break; |
||||
case WARNING: |
||||
if (logger.isWarnEnabled()) { |
||||
if (entry.hasException()) { |
||||
logger.warn(getMessageString(entry), getException(entry)); |
||||
} |
||||
else { |
||||
logger.warn(getMessageString(entry)); |
||||
} |
||||
} |
||||
break; |
||||
case INFO: |
||||
if (logger.isInfoEnabled()) { |
||||
if (entry.hasException()) { |
||||
logger.info(getMessageString(entry), getException(entry)); |
||||
} |
||||
else { |
||||
logger.info(getMessageString(entry)); |
||||
} |
||||
} |
||||
break; |
||||
case CONFIG: |
||||
case FINE: |
||||
case FINER: |
||||
if (logger.isDebugEnabled()) { |
||||
if (entry.hasException()) { |
||||
logger.debug(getMessageString(entry), getException(entry)); |
||||
} |
||||
else { |
||||
logger.debug(getMessageString(entry)); |
||||
} |
||||
} |
||||
break; |
||||
case FINEST: |
||||
if (logger.isTraceEnabled()) { |
||||
if (entry.hasException()) { |
||||
logger.trace(getMessageString(entry), getException(entry)); |
||||
} |
||||
else { |
||||
logger.trace(getMessageString(entry)); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determine the log category for the given log entry. |
||||
* <p>If the entry carries a name space value, it will be appended |
||||
* to the "oracle.toplink." prefix; else, "oracle.toplink.session" |
||||
* will be used. |
||||
*/ |
||||
protected String getCategory(SessionLogEntry entry) { |
||||
String namespace = entry.getNameSpace(); |
||||
return NAMESPACE_PREFIX + (namespace != null ? namespace : DEFAULT_NAMESPACE); |
||||
} |
||||
|
||||
/** |
||||
* Build the message String for the given log entry, including the |
||||
* supplemental details (session, connection) and the formatted message. |
||||
* @see #getSessionString(oracle.toplink.sessions.Session) |
||||
* @see #getConnectionString(oracle.toplink.internal.databaseaccess.Accessor) |
||||
* @see #formatMessage(oracle.toplink.logging.SessionLogEntry) |
||||
* @see #getSeparator() |
||||
*/ |
||||
protected String getMessageString(SessionLogEntry entry) { |
||||
StringBuffer buf = new StringBuffer(); |
||||
Session session = getSession(entry); |
||||
if (session != null) { |
||||
buf.append(getSessionString(session)); |
||||
buf.append(getSeparator()); |
||||
} |
||||
Accessor connection = entry.getConnection(); |
||||
if (connection != null) { |
||||
buf.append(getConnectionString(connection)); |
||||
buf.append(getSeparator()); |
||||
} |
||||
buf.append(formatMessage(entry)); |
||||
return buf.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Extract the exception from the given log entry. |
||||
* <p>The default implementation calls <code>SessionLogEntry.getSession</code> |
||||
* via reflection: The return type varies between TopLink 10.1.3 and 11 |
||||
* (<code>Session</code> vs <code>AbstractSession</code>, respectively). |
||||
*/ |
||||
protected Session getSession(SessionLogEntry entry) { |
||||
return (Session) ReflectionUtils.invokeMethod(getSessionMethod, entry); |
||||
} |
||||
|
||||
/** |
||||
* Extract the exception from the given log entry. |
||||
* <p>The default implementation calls <code>SessionLogEntry.getException</code> |
||||
* via reflection: The return type varies between TopLink 9.0.4 and 10.1.3 |
||||
* (<code>Exception</code> vs <code>Throwable</code>, respectively). |
||||
*/ |
||||
protected Throwable getException(SessionLogEntry entry) { |
||||
return (Throwable) ReflectionUtils.invokeMethod(getExceptionMethod, entry); |
||||
} |
||||
|
||||
} |
||||
@ -1,148 +0,0 @@
@@ -1,148 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink.support; |
||||
|
||||
import oracle.toplink.sessions.DefaultSessionLog; |
||||
import oracle.toplink.sessions.Session; |
||||
import oracle.toplink.sessions.SessionLogEntry; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* TopLink 9.0.4 SessionLog implementation that logs through Commons Logging. |
||||
* |
||||
* <p>The namespace used is "oracle.toplink.session". Fine-grained filtering |
||||
* of log messages, for example through Log4J configuration, is <i>not</i> |
||||
* available on TopLink 9.0.4: Consider upgrading to TopLink 10.1.3 and |
||||
* using the CommonsLoggingSessionLog class instead. |
||||
* |
||||
* <p>TopLink log entries with exceptions are logged at CL WARN level, |
||||
* TopLink debug log entries at CL TRACE level, and any other log entry |
||||
* at CL DEBUG level. Finer-grained mapping to log levels is unfortunately |
||||
* not possible on TopLink 9.0.4. |
||||
* |
||||
* <p><b>Note:</b> This implementation will only actually work on TopLink 9.0.4, |
||||
* as it is built against TopLink's old SessionLog facilities in the |
||||
* <code>oracle.toplink.sessions</code> package, which are effectively |
||||
* obsolete (deprecated and bypassed) as of TopLink 10.1.3. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see CommonsLoggingSessionLog |
||||
* @see oracle.toplink.sessions.DefaultSessionLog |
||||
* @see org.springframework.orm.toplink.LocalSessionFactoryBean#setSessionLog |
||||
*/ |
||||
public class CommonsLoggingSessionLog904 extends DefaultSessionLog { |
||||
|
||||
public static final String NAMESPACE = "oracle.toplink.session"; |
||||
|
||||
public static final String DEFAULT_SEPARATOR = "--"; |
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(NAMESPACE); |
||||
|
||||
private String separator = DEFAULT_SEPARATOR; |
||||
|
||||
|
||||
/** |
||||
* Specify the separator between TopLink's supplemental details |
||||
* (session, connection) and the log message itself. Default is "--". |
||||
*/ |
||||
public void setSeparator(String separator) { |
||||
this.separator = separator; |
||||
} |
||||
|
||||
/** |
||||
* Return the separator between TopLink's supplemental details |
||||
* (session, connection) and the log message itself. Default is "--". |
||||
*/ |
||||
public String getSeparator() { |
||||
return separator; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void log(SessionLogEntry entry) { |
||||
if (entry.hasException()) { |
||||
if (shouldLogExceptions() && logger.isWarnEnabled()) { |
||||
this.logger.warn(getMessageString(entry), entry.getException()); |
||||
} |
||||
} |
||||
else if (entry.isDebug()) { |
||||
if (shouldLogDebug() && logger.isTraceEnabled()) { |
||||
this.logger.trace(getMessageString(entry)); |
||||
} |
||||
} |
||||
else { |
||||
if (logger.isDebugEnabled()) { |
||||
this.logger.debug(getMessageString(entry)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Build the message String for the given log entry, including the |
||||
* supplemental details (session, connection) and the message text. |
||||
* @see #getSeparator() |
||||
*/ |
||||
protected String getMessageString(SessionLogEntry entry) { |
||||
StringBuffer buf = new StringBuffer(); |
||||
if (shouldPrintSession()) { |
||||
buf.append(getSessionName(entry.getSession())); |
||||
buf.append("("); |
||||
buf.append(String.valueOf(System.identityHashCode(entry.getSession()))); |
||||
buf.append(")"); |
||||
buf.append(getSeparator()); |
||||
} |
||||
if (shouldPrintConnection() && entry.getConnection() != null) { |
||||
buf.append("Connection"); |
||||
buf.append("("); |
||||
buf.append(String.valueOf(System.identityHashCode(entry.getConnection()))); |
||||
buf.append(")"); |
||||
buf.append(getSeparator()); |
||||
} |
||||
buf.append(entry.getMessage()); |
||||
return buf.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Return the name to be used for the given Session |
||||
* ("UnitOfWork"/"ServerSession"/"ClientSession"/etc). |
||||
*/ |
||||
protected String getSessionName(Session session) { |
||||
if (session.isUnitOfWork()) { |
||||
return "UnitOfWork"; |
||||
} |
||||
if (session.isServerSession()) { |
||||
return "ServerSession"; |
||||
} |
||||
if (session.isClientSession()) { |
||||
return "ClientSession"; |
||||
} |
||||
if (session.isSessionBroker()) { |
||||
return "SessionBroker"; |
||||
} |
||||
if (session.isRemoteSession()) { |
||||
return "RemoteSession"; |
||||
} |
||||
if (session.isDatabaseSession()) { |
||||
return "DatabaseSession"; |
||||
} |
||||
return "Session"; |
||||
} |
||||
|
||||
} |
||||
@ -1,192 +0,0 @@
@@ -1,192 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2008 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.toplink.support; |
||||
|
||||
import oracle.toplink.exceptions.TopLinkException; |
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.dao.DataAccessResourceFailureException; |
||||
import org.springframework.dao.support.DaoSupport; |
||||
import org.springframework.orm.toplink.SessionFactory; |
||||
import org.springframework.orm.toplink.SessionFactoryUtils; |
||||
import org.springframework.orm.toplink.TopLinkTemplate; |
||||
|
||||
/** |
||||
* Convenient super class for TopLink data access objects. |
||||
* |
||||
* <p>Requires a SessionFactory to be set, providing a TopLinkTemplate |
||||
* based on it to subclasses. Can alternatively be initialized directly with |
||||
* a TopLinkTemplate, to reuse the latter's settings such as the SessionFactory, |
||||
* exception translator, etc. |
||||
* |
||||
* <p>This base class is mainly intended for TopLinkTemplate usage |
||||
* but can also be used when working with SessionFactoryUtils directly, |
||||
* for example in combination with TopLinkInterceptor-managed Sessions. |
||||
* Convenience <code>getSession</code> and <code>releaseSession</code> |
||||
* methods are provided for that usage style. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see #setSessionFactory |
||||
* @see #setTopLinkTemplate |
||||
* @see #getSession |
||||
* @see #releaseSession |
||||
* @see org.springframework.orm.toplink.TopLinkTemplate |
||||
* @see org.springframework.orm.toplink.TopLinkInterceptor |
||||
*/ |
||||
public abstract class TopLinkDaoSupport extends DaoSupport { |
||||
|
||||
private TopLinkTemplate topLinkTemplate; |
||||
|
||||
|
||||
/** |
||||
* Set the TopLink SessionFactory to be used by this DAO. |
||||
* Will automatically create a TopLinkTemplate for the given SessionFactory. |
||||
* @see #createTopLinkTemplate |
||||
* @see #setTopLinkTemplate |
||||
*/ |
||||
public final void setSessionFactory(SessionFactory sessionFactory) { |
||||
if (this.topLinkTemplate == null || sessionFactory != this.topLinkTemplate.getSessionFactory()) { |
||||
this.topLinkTemplate = createTopLinkTemplate(sessionFactory); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create a TopLinkTemplate for the given SessionFactory. |
||||
* Only invoked if populating the DAO with a SessionFactory reference! |
||||
* <p>Can be overridden in subclasses to provide a TopLinkTemplate instance |
||||
* with different configuration, or a custom TopLinkTemplate subclass. |
||||
* @param sessionFactory the TopLink SessionFactory to create a TopLinkTemplate for |
||||
* @return the new TopLinkTemplate instance |
||||
* @see #setSessionFactory |
||||
*/ |
||||
protected TopLinkTemplate createTopLinkTemplate(SessionFactory sessionFactory) { |
||||
return new TopLinkTemplate(sessionFactory); |
||||
} |
||||
|
||||
/** |
||||
* Return the TopLink SessionFactory used by this DAO. |
||||
*/ |
||||
public final SessionFactory getSessionFactory() { |
||||
return (this.topLinkTemplate != null ? this.topLinkTemplate.getSessionFactory() : null); |
||||
} |
||||
|
||||
/** |
||||
* Set the TopLinkTemplate for this DAO explicitly, |
||||
* as an alternative to specifying a SessionFactory. |
||||
* @see #setSessionFactory |
||||
*/ |
||||
public final void setTopLinkTemplate(TopLinkTemplate topLinkTemplate) { |
||||
this.topLinkTemplate = topLinkTemplate; |
||||
} |
||||
|
||||
/** |
||||
* Return the TopLinkTemplate for this DAO, |
||||
* pre-initialized with the SessionFactory or set explicitly. |
||||
*/ |
||||
public final TopLinkTemplate getTopLinkTemplate() { |
||||
return topLinkTemplate; |
||||
} |
||||
|
||||
@Override |
||||
protected final void checkDaoConfig() { |
||||
if (this.topLinkTemplate == null) { |
||||
throw new IllegalArgumentException("sessionFactory or topLinkTemplate is required"); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get a TopLink Session, either from the current transaction or a new one. |
||||
* The latter is only allowed if the "allowCreate" setting of this bean's |
||||
* TopLinkTemplate is true. |
||||
* <p><b>Note that this is not meant to be invoked from TopLinkTemplate code |
||||
* but rather just in plain TopLink code.</b> Either rely on a thread-bound |
||||
* Session (via TopLinkInterceptor), or use it in combination with |
||||
* <code>releaseSession</code>. |
||||
* <p>In general, it is recommended to use TopLinkTemplate, either with |
||||
* the provided convenience operations or with a custom TopLinkCallback |
||||
* that provides you with a Session to work on. TopLinkTemplate will care |
||||
* for all resource management and for proper exception conversion. |
||||
* @return the TopLink Session |
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created |
||||
* @throws IllegalStateException if no thread-bound Session found and allowCreate false |
||||
* @see TopLinkTemplate |
||||
* @see org.springframework.orm.toplink.SessionFactoryUtils#getSession(SessionFactory, boolean) |
||||
* @see org.springframework.orm.toplink.TopLinkInterceptor |
||||
* @see org.springframework.orm.toplink.TopLinkTemplate |
||||
* @see org.springframework.orm.toplink.TopLinkCallback |
||||
*/ |
||||
protected final Session getSession() |
||||
throws DataAccessResourceFailureException, IllegalStateException { |
||||
|
||||
return getSession(this.topLinkTemplate.isAllowCreate()); |
||||
} |
||||
|
||||
/** |
||||
* Get a TopLink Session, either from the current transaction or a new one. |
||||
* The latter is only allowed if "allowCreate" is true. |
||||
* <p><b>Note that this is not meant to be invoked from TopLinkTemplate code |
||||
* but rather just in plain TopLink code.</b> Either rely on a thread-bound |
||||
* Session (via TopLinkInterceptor), or use it in combination with |
||||
* <code>releaseSession</code>. |
||||
* <p>In general, it is recommended to use TopLinkTemplate, either with |
||||
* the provided convenience operations or with a custom TopLinkCallback |
||||
* that provides you with a Session to work on. TopLinkTemplate will care |
||||
* for all resource management and for proper exception conversion. |
||||
* @param allowCreate if a new Session should be created if no thread-bound found |
||||
* @return the TopLink Session |
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created |
||||
* @throws IllegalStateException if no thread-bound Session found and allowCreate false |
||||
* @see org.springframework.orm.toplink.SessionFactoryUtils#getSession(SessionFactory, boolean) |
||||
* @see org.springframework.orm.toplink.TopLinkInterceptor |
||||
* @see org.springframework.orm.toplink.TopLinkTemplate |
||||
* @see org.springframework.orm.toplink.TopLinkCallback |
||||
*/ |
||||
protected final Session getSession(boolean allowCreate) |
||||
throws DataAccessResourceFailureException, IllegalStateException { |
||||
|
||||
return SessionFactoryUtils.getSession(this.getSessionFactory(), allowCreate); |
||||
} |
||||
|
||||
/** |
||||
* Convert the given TopLinkException to an appropriate exception from the |
||||
* <code>org.springframework.dao</code> hierarchy. Will automatically detect |
||||
* wrapped SQLExceptions and convert them accordingly. |
||||
* <p>Delegates to the convertTopLinkAccessException method of this |
||||
* DAO's TopLinkTemplate. |
||||
* @param ex TopLinkException that occured |
||||
* @return the corresponding DataAccessException instance |
||||
* @see #setTopLinkTemplate |
||||
* @see org.springframework.orm.toplink.TopLinkTemplate#convertTopLinkAccessException |
||||
*/ |
||||
protected final DataAccessException convertTopLinkAccessException(TopLinkException ex) { |
||||
return this.topLinkTemplate.convertTopLinkAccessException(ex); |
||||
} |
||||
|
||||
/** |
||||
* Close the given TopLink Session, created via this DAO's SessionFactory, |
||||
* if it isn't bound to the thread. |
||||
* @param session the TopLink Session to close |
||||
* @see org.springframework.orm.toplink.SessionFactoryUtils#releaseSession |
||||
*/ |
||||
protected final void releaseSession(Session session) { |
||||
SessionFactoryUtils.releaseSession(session, getSessionFactory()); |
||||
} |
||||
|
||||
} |
||||
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2005 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.toplink.support; |
||||
|
||||
import oracle.toplink.sessions.Session; |
||||
|
||||
import org.springframework.beans.factory.FactoryBean; |
||||
import org.springframework.orm.toplink.SessionFactory; |
||||
|
||||
/** |
||||
* This adapter FactoryBean takes a TopLink SessionFactory and exposes a |
||||
* corresponding transaction-aware TopLink Session as bean reference. |
||||
* |
||||
* <p>This adapter bean will usually be defined in front of a Spring |
||||
* LocalSessionFactoryBean, to allow for passing Session references to DAOs |
||||
* that expect to work on a raw TopLink Session. Your DAOs can then, |
||||
* for example, access the currently active Session and UnitOfWork via |
||||
* <code>Session.getActiveSession()</code> and |
||||
* <code>Session.getActiveUnitOfWork()</code>, respectively. |
||||
* |
||||
* <p>The main advantage of this proxy is that it allows DAOs to work with a |
||||
* plain TopLink Session reference, while still participating in Spring's |
||||
* (or a J2EE server's) resource and transaction management. DAOs will only |
||||
* rely on the TopLink API in such a scenario, without any Spring dependencies. |
||||
* |
||||
* <p>It is usually preferable to write your TopLink-based DAOs with Spring's |
||||
* TopLinkTemplate, offering benefits such as consistent data access exceptions |
||||
* instead of TopLinkExceptions at the DAO layer. However, Spring's resource |
||||
* and transaction management (and Dependency Injection) will work for DAOs |
||||
* written against the plain TopLink API too. |
||||
* |
||||
* <p>Of course, you can still access the target TopLink SessionFactory |
||||
* even when your DAOs go through this adapter, by defining a bean reference |
||||
* that points directly at your target SessionFactory bean. |
||||
* |
||||
* <p>Note that the actual creation of a transaction-aware TopLink Session |
||||
* is available on the TopLink SessionFactory itself. This adapter FactoryBean |
||||
* is just a convenient way to expose such a Session in a declarative fashion. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 1.2 |
||||
* @see org.springframework.orm.toplink.LocalSessionFactoryBean |
||||
* @see org.springframework.orm.toplink.SessionFactory#createTransactionAwareSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveSession() |
||||
* @see oracle.toplink.sessions.Session#getActiveUnitOfWork() |
||||
*/ |
||||
public class TransactionAwareSessionAdapter implements FactoryBean { |
||||
|
||||
private Session session; |
||||
|
||||
|
||||
/** |
||||
* Set the SessionFactory that this adapter is supposed to expose a |
||||
* transaction-aware TopLink Session for. This should be the raw |
||||
* SessionFactory, as accessed by TopLinkTransactionManager. |
||||
* @see org.springframework.orm.toplink.TopLinkTransactionManager |
||||
*/ |
||||
public void setSessionFactory(SessionFactory sessionFactory) { |
||||
this.session = sessionFactory.createTransactionAwareSession(); |
||||
} |
||||
|
||||
|
||||
public Object getObject() { |
||||
return this.session; |
||||
} |
||||
|
||||
public Class getObjectType() { |
||||
return Session.class; |
||||
} |
||||
|
||||
public boolean isSingleton() { |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -1,8 +0,0 @@
@@ -1,8 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Classes supporting the <code>org.springframework.orm.toplink</code> package. |
||||
Contains a DAO base class for TopLinkTemplate usage. |
||||
|
||||
</body> |
||||
</html> |
||||
Loading…
Reference in new issue