View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2014年3月28日 下午5:59:32
4    */
5   package gboat2.base.dao.impl;
6   
7   import gboat2.base.dao.aspect.SessionFactoryHolder;
8   
9   import java.util.ArrayList;
10  import java.util.Collections;
11  import java.util.List;
12  
13  import org.hibernate.HibernateException;
14  import org.hibernate.Session;
15  import org.hibernate.SessionFactory;
16  import org.springframework.dao.DataAccessResourceFailureException;
17  import org.springframework.dao.support.DaoSupport;
18  import org.springframework.orm.hibernate3.HibernateTemplate;
19  import org.springframework.orm.hibernate3.SessionFactoryUtils;
20  
21  /**
22   * 因为 {@link org.springframework.orm.hibernate3.support.HibernateDaoSupport} 的
23   * {@link #getHibernateTemplate()} 等方法都是 final
24   * 的,不能被重写,所以平台自定义一个 HibernateDaoSupport,以解决 Spring 内置的 HibernateDaoSupport 类的限制
25   * 
26   * @author <a href="mailto:[email protected]">何明旺</a>
27   * @since 3.0
28   * @date 2014年3月28日
29   */
30  public class GboatHibernateDaoSupport extends DaoSupport {
31  
32      private static List<HibernateTemplate> hibernateTemplates = Collections.synchronizedList(new ArrayList<HibernateTemplate>());
33      private HibernateTemplate defaultHibernateTemplate;
34  
35      public void setDefaultSessionFactory(SessionFactory sessionFactory) {
36          if (this.defaultHibernateTemplate == null || sessionFactory != this.defaultHibernateTemplate.getSessionFactory()) {
37              this.defaultHibernateTemplate = createHibernateTemplate(sessionFactory);
38          }
39      }
40      
41      public SessionFactory getDefaultSessionFactory() {
42          return getDefaultHibernateTemplate().getSessionFactory();
43      }
44  
45      /**
46       * Return the Hibernate SessionFactory used by this DAO.
47       */
48      public SessionFactory getSessionFactory() {
49          HibernateTemplate hibernateTemplate = this.getHibernateTemplate();
50          return (hibernateTemplate != null ? hibernateTemplate.getSessionFactory() : null);
51      }
52  
53      public void addSessionFactory(SessionFactory sessionFactory) {
54          for (HibernateTemplate template : hibernateTemplates) {
55              if(template.getSessionFactory().equals(sessionFactory))
56                  return;
57          }
58          
59          HibernateTemplate template = createHibernateTemplate(sessionFactory);
60          hibernateTemplates.add(template);
61      }
62  
63      public void setDefaultHibernateTemplate(HibernateTemplate defaultHibernateTemplate) {
64          this.defaultHibernateTemplate = defaultHibernateTemplate;
65      }
66  
67      public HibernateTemplate getDefaultHibernateTemplate() {
68          return defaultHibernateTemplate;
69      }
70  
71      /**
72       * Return the HibernateTemplate for this DAO,
73       * pre-initialized with the SessionFactory or set explicitly.
74       * <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
75       * You may introspect its configuration, but not modify the configuration
76       * (other than from within an {@link #initDao} implementation).
77       * Consider creating a custom HibernateTemplate instance via
78       * {@code new HibernateTemplate(getSessionFactory())}, in which
79       * case you're allowed to customize the settings on the resulting instance.
80       */
81      public HibernateTemplate getHibernateTemplate() {
82          SessionFactory sessionFactory = SessionFactoryHolder.getSessionFactory();
83          if(sessionFactory == null)
84              return this.defaultHibernateTemplate;
85          
86          for (HibernateTemplate template : hibernateTemplates) {
87              if(template.getSessionFactory().equals(sessionFactory))
88                  return template;
89          }
90  
91          throw new HibernateException("没有与当前 SessionFactory 相匹配的 HibernateTemplate 实例。");
92      }
93  
94      /**
95       * Create a HibernateTemplate for the given SessionFactory.
96       * Only invoked if populating the DAO with a SessionFactory reference!
97       * <p>Can be overridden in subclasses to provide a HibernateTemplate instance
98       * with different configuration, or a custom HibernateTemplate subclass.
99       * @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
100      * @return the new HibernateTemplate instance
101      * @see #setSessionFactory
102      */
103     protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
104         return new HibernateTemplate(sessionFactory);
105     }
106 
107     /**
108      * Obtain a Hibernate Session, either from the current transaction or
109      * a new one. The latter is only allowed if the
110      * {@link org.springframework.orm.hibernate3.HibernateTemplate#setAllowCreate "allowCreate"}
111      * setting of this bean's {@link #setHibernateTemplate HibernateTemplate} is "true".
112      * <p><b>Note that this is not meant to be invoked from HibernateTemplate code
113      * but rather just in plain Hibernate code.</b> Either rely on a thread-bound
114      * Session or use it in combination with {@link #releaseSession}.
115      * <p>In general, it is recommended to use HibernateTemplate, either with
116      * the provided convenience operations or with a custom HibernateCallback
117      * that provides you with a Session to work on. HibernateTemplate will care
118      * for all resource management and for proper exception conversion.
119      * @return the Hibernate Session
120      * @throws DataAccessResourceFailureException if the Session couldn't be created
121      * @throws IllegalStateException if no thread-bound Session found and allowCreate=false
122      * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
123      */
124     protected Session getSession() throws DataAccessResourceFailureException, IllegalStateException {
125         return getSession(this.getHibernateTemplate().isAllowCreate());
126     }
127 
128     /**
129      * Obtain a Hibernate Session, either from the current transaction or
130      * a new one. The latter is only allowed if "allowCreate" is true.
131      * <p><b>Note that this is not meant to be invoked from HibernateTemplate code
132      * but rather just in plain Hibernate code.</b> Either rely on a thread-bound
133      * Session or use it in combination with {@link #releaseSession}.
134      * <p>In general, it is recommended to use
135      * {@link #getHibernateTemplate() HibernateTemplate}, either with
136      * the provided convenience operations or with a custom
137      * {@link org.springframework.orm.hibernate3.HibernateCallback} that
138      * provides you with a Session to work on. HibernateTemplate will care
139      * for all resource management and for proper exception conversion.
140      * @param allowCreate if a non-transactional Session should be created when no
141      * transactional Session can be found for the current thread
142      * @return the Hibernate Session
143      * @throws DataAccessResourceFailureException if the Session couldn't be created
144      * @throws IllegalStateException if no thread-bound Session found and allowCreate=false
145      * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
146      */
147     protected Session getSession(boolean allowCreate) throws DataAccessResourceFailureException, IllegalStateException {
148         HibernateTemplate hibernateTemplate = this.getHibernateTemplate();
149         return (!allowCreate ?
150             SessionFactoryUtils.getSession(getSessionFactory(), false) :
151                 SessionFactoryUtils.getSession(
152                         getSessionFactory(),
153                         hibernateTemplate.getEntityInterceptor(),
154                         hibernateTemplate.getJdbcExceptionTranslator()));
155     }
156     
157     @Override
158     protected void checkDaoConfig() throws IllegalArgumentException {
159         if (this.defaultHibernateTemplate == null) {
160             throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");
161         }
162     }
163 
164 }