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