001/*
002 * Copyright 2002-2015 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 *      https://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
017package org.springframework.orm.hibernate5.support;
018
019import org.hibernate.Session;
020import org.hibernate.SessionFactory;
021
022import org.springframework.dao.DataAccessResourceFailureException;
023import org.springframework.dao.support.DaoSupport;
024import org.springframework.orm.hibernate5.HibernateTemplate;
025
026/**
027 * Convenient super class for Hibernate-based data access objects.
028 *
029 * <p>Requires a {@link SessionFactory} to be set, providing a
030 * {@link org.springframework.orm.hibernate5.HibernateTemplate} based on it to
031 * subclasses through the {@link #getHibernateTemplate()} method.
032 * Can alternatively be initialized directly with a HibernateTemplate,
033 * in order to reuse the latter's settings such as the SessionFactory,
034 * exception translator, flush mode, etc.
035 *
036 * <p>This class will create its own HibernateTemplate instance if a SessionFactory
037 * is passed in. The "allowCreate" flag on that HibernateTemplate will be "true"
038 * by default. A custom HibernateTemplate instance can be used through overriding
039 * {@link #createHibernateTemplate}.
040 *
041 * <p><b>NOTE: Hibernate access code can also be coded in plain Hibernate style.
042 * Hence, for newly started projects, consider adopting the standard Hibernate
043 * style of coding data access objects instead, based on
044 * {@link SessionFactory#getCurrentSession()}.
045 * This HibernateTemplate primarily exists as a migration helper for Hibernate 3
046 * based data access code, to benefit from bug fixes in Hibernate 5.x.</b>
047 *
048 * @author Juergen Hoeller
049 * @since 4.2
050 * @see #setSessionFactory
051 * @see #getHibernateTemplate
052 * @see org.springframework.orm.hibernate5.HibernateTemplate
053 */
054public abstract class HibernateDaoSupport extends DaoSupport {
055
056        private HibernateTemplate hibernateTemplate;
057
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                if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {
067                        this.hibernateTemplate = createHibernateTemplate(sessionFactory);
068                }
069        }
070
071        /**
072         * Create a HibernateTemplate for the given SessionFactory.
073         * Only invoked if populating the DAO with a SessionFactory reference!
074         * <p>Can be overridden in subclasses to provide a HibernateTemplate instance
075         * with different configuration, or a custom HibernateTemplate subclass.
076         * @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
077         * @return the new HibernateTemplate instance
078         * @see #setSessionFactory
079         */
080        protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
081                return new HibernateTemplate(sessionFactory);
082        }
083
084        /**
085         * Return the Hibernate SessionFactory used by this DAO.
086         */
087        public final SessionFactory getSessionFactory() {
088                return (this.hibernateTemplate != null ? this.hibernateTemplate.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(HibernateTemplate hibernateTemplate) {
097                this.hibernateTemplate = hibernateTemplate;
098        }
099
100        /**
101         * Return the HibernateTemplate for this DAO,
102         * pre-initialized with the SessionFactory or set explicitly.
103         * <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
104         * You may introspect its configuration, but not modify the configuration
105         * (other than from within an {@link #initDao} implementation).
106         * Consider creating a custom HibernateTemplate instance via
107         * {@code new HibernateTemplate(getSessionFactory())}, in which case
108         * you're allowed to customize the settings on the resulting instance.
109         */
110        public final HibernateTemplate getHibernateTemplate() {
111          return this.hibernateTemplate;
112        }
113
114        @Override
115        protected final void checkDaoConfig() {
116                if (this.hibernateTemplate == null) {
117                        throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");
118                }
119        }
120
121
122        /**
123         * Conveniently obtain the current Hibernate Session.
124         * @return the Hibernate Session
125         * @throws DataAccessResourceFailureException if the Session couldn't be created
126         * @see SessionFactory#getCurrentSession()
127         */
128        protected final Session currentSession() throws DataAccessResourceFailureException {
129                return getSessionFactory().getCurrentSession();
130        }
131
132}