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