27 changed files with 0 additions and 4530 deletions
@ -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; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue