001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.orm.hibernate3.support;
018:
019: import org.hibernate.HibernateException;
020: import org.hibernate.Session;
021: import org.hibernate.SessionFactory;
022:
023: import org.springframework.dao.DataAccessException;
024: import org.springframework.dao.DataAccessResourceFailureException;
025: import org.springframework.dao.support.DaoSupport;
026: import org.springframework.orm.hibernate3.HibernateTemplate;
027: import org.springframework.orm.hibernate3.SessionFactoryUtils;
028:
029: /**
030: * Convenient super class for Hibernate-based data access objects.
031: *
032: * <p>Requires a {@link org.hibernate.SessionFactory} to be set, providing a
033: * {@link org.springframework.orm.hibernate3.HibernateTemplate} based on it to
034: * subclasses through the {@link #getHibernateTemplate()} method.
035: * Can alternatively be initialized directly with a HibernateTemplate,
036: * in order to reuse the latter's settings such as the SessionFactory,
037: * exception translator, flush mode, etc.
038: *
039: * <p>This base class is mainly intended for HibernateTemplate usage but can
040: * also be used when working with a Hibernate Session directly, for example
041: * when relying on transactional Sessions. Convenience {@link #getSession}
042: * and {@link #releaseSession} methods are provided for that usage style.
043: *
044: * <p>This class will create its own HibernateTemplate instance if a SessionFactory
045: * is passed in. The "allowCreate" flag on that HibernateTemplate will be "true"
046: * by default. A custom HibernateTemplate instance can be used through overriding
047: * {@link #createHibernateTemplate}.
048: *
049: * @author Juergen Hoeller
050: * @since 1.2
051: * @see #setSessionFactory
052: * @see #getHibernateTemplate
053: * @see org.springframework.orm.hibernate3.HibernateTemplate
054: */
055: public abstract class HibernateDaoSupport extends DaoSupport {
056:
057: private HibernateTemplate hibernateTemplate;
058:
059: /**
060: * Set the Hibernate SessionFactory to be used by this DAO.
061: * Will automatically create a HibernateTemplate for the given SessionFactory.
062: * @see #createHibernateTemplate
063: * @see #setHibernateTemplate
064: */
065: public final void setSessionFactory(SessionFactory sessionFactory) {
066: this .hibernateTemplate = createHibernateTemplate(sessionFactory);
067: }
068:
069: /**
070: * Create a HibernateTemplate for the given SessionFactory.
071: * Only invoked if populating the DAO with a SessionFactory reference!
072: * <p>Can be overridden in subclasses to provide a HibernateTemplate instance
073: * with different configuration, or a custom HibernateTemplate subclass.
074: * @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
075: * @return the new HibernateTemplate instance
076: * @see #setSessionFactory
077: */
078: protected HibernateTemplate createHibernateTemplate(
079: SessionFactory sessionFactory) {
080: return new HibernateTemplate(sessionFactory);
081: }
082:
083: /**
084: * Return the Hibernate SessionFactory used by this DAO.
085: */
086: public final SessionFactory getSessionFactory() {
087: return (this .hibernateTemplate != null ? this .hibernateTemplate
088: .getSessionFactory() : null);
089: }
090:
091: /**
092: * Set the HibernateTemplate for this DAO explicitly,
093: * as an alternative to specifying a SessionFactory.
094: * @see #setSessionFactory
095: */
096: public final void setHibernateTemplate(
097: HibernateTemplate hibernateTemplate) {
098: this .hibernateTemplate = hibernateTemplate;
099: }
100:
101: /**
102: * Return the HibernateTemplate for this DAO,
103: * pre-initialized with the SessionFactory or set explicitly.
104: * <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
105: * You may introspect its configuration, but not modify the configuration
106: * (other than from within an {@link #initDao} implementation).
107: * Consider creating a custom HibernateTemplate instance via
108: * <code>new HibernateTemplate(getSessionFactory())</code>, in which
109: * case you're allowed to customize the settings on the resulting instance.
110: */
111: public final HibernateTemplate getHibernateTemplate() {
112: return this .hibernateTemplate;
113: }
114:
115: protected final void checkDaoConfig() {
116: if (this .hibernateTemplate == null) {
117: throw new IllegalArgumentException(
118: "'sessionFactory' or 'hibernateTemplate' is required");
119: }
120: }
121:
122: /**
123: * Obtain a Hibernate Session, either from the current transaction or
124: * a new one. The latter is only allowed if the
125: * {@link org.springframework.orm.hibernate3.HibernateTemplate#setAllowCreate "allowCreate"}
126: * setting of this bean's {@link #setHibernateTemplate HibernateTemplate} is "true".
127: * <p><b>Note that this is not meant to be invoked from HibernateTemplate code
128: * but rather just in plain Hibernate code.</b> Either rely on a thread-bound
129: * Session or use it in combination with {@link #releaseSession}.
130: * <p>In general, it is recommended to use HibernateTemplate, either with
131: * the provided convenience operations or with a custom HibernateCallback
132: * that provides you with a Session to work on. HibernateTemplate will care
133: * for all resource management and for proper exception conversion.
134: * @return the Hibernate Session
135: * @throws DataAccessResourceFailureException if the Session couldn't be created
136: * @throws IllegalStateException if no thread-bound Session found and allowCreate=false
137: * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
138: */
139: protected final Session getSession()
140: throws DataAccessResourceFailureException,
141: IllegalStateException {
142:
143: return getSession(this .hibernateTemplate.isAllowCreate());
144: }
145:
146: /**
147: * Obtain a Hibernate Session, either from the current transaction or
148: * a new one. The latter is only allowed if "allowCreate" is true.
149: * <p><b>Note that this is not meant to be invoked from HibernateTemplate code
150: * but rather just in plain Hibernate code.</b> Either rely on a thread-bound
151: * Session or use it in combination with {@link #releaseSession}.
152: * <p>In general, it is recommended to use
153: * {@link #getHibernateTemplate() HibernateTemplate}, either with
154: * the provided convenience operations or with a custom
155: * {@link org.springframework.orm.hibernate3.HibernateCallback} that
156: * provides you with a Session to work on. HibernateTemplate will care
157: * for all resource management and for proper exception conversion.
158: * @param allowCreate if a non-transactional Session should be created when no
159: * transactional Session can be found for the current thread
160: * @return the Hibernate Session
161: * @throws DataAccessResourceFailureException if the Session couldn't be created
162: * @throws IllegalStateException if no thread-bound Session found and allowCreate=false
163: * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
164: */
165: protected final Session getSession(boolean allowCreate)
166: throws DataAccessResourceFailureException,
167: IllegalStateException {
168:
169: return (!allowCreate ? SessionFactoryUtils.getSession(
170: getSessionFactory(), false) : SessionFactoryUtils
171: .getSession(getSessionFactory(), this .hibernateTemplate
172: .getEntityInterceptor(), this .hibernateTemplate
173: .getJdbcExceptionTranslator()));
174: }
175:
176: /**
177: * Convert the given HibernateException to an appropriate exception from the
178: * <code>org.springframework.dao</code> hierarchy. Will automatically detect
179: * wrapped SQLExceptions and convert them accordingly.
180: * <p>Delegates to the
181: * {@link org.springframework.orm.hibernate3.HibernateTemplate#convertHibernateAccessException}
182: * method of this DAO's HibernateTemplate.
183: * <p>Typically used in plain Hibernate code, in combination with
184: * {@link #getSession} and {@link #releaseSession}.
185: * @param ex HibernateException that occured
186: * @return the corresponding DataAccessException instance
187: * @see org.springframework.orm.hibernate3.SessionFactoryUtils#convertHibernateAccessException
188: */
189: protected final DataAccessException convertHibernateAccessException(
190: HibernateException ex) {
191: return this .hibernateTemplate
192: .convertHibernateAccessException(ex);
193: }
194:
195: /**
196: * Close the given Hibernate Session, created via this DAO's SessionFactory,
197: * if it isn't bound to the thread (i.e. isn't a transactional Session).
198: * <p>Typically used in plain Hibernate code, in combination with
199: * {@link #getSession} and {@link #convertHibernateAccessException}.
200: * @param session the Session to close
201: * @see org.springframework.orm.hibernate3.SessionFactoryUtils#releaseSession
202: */
203: protected final void releaseSession(Session session) {
204: SessionFactoryUtils
205: .releaseSession(session, getSessionFactory());
206: }
207:
208: }
|