Removed raw TopLink support

This commit is contained in:
Arjen Poutsma 2008-10-30 16:51:09 +00:00
parent 434c744842
commit 11a2e40d41
27 changed files with 0 additions and 4530 deletions

View File

@ -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();
}
}
}
}

View File

@ -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 &lt;login&gt; 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 &lt;login&gt; 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);
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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());
}
}
}
}

View File

@ -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());
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
});
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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";
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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>