Java Spring: AnnotationSessionFactoryBean, Hibernate-Dialect AutoDetection

theomega picture theomega · Oct 6, 2009 · Viewed 7.1k times · Source

I use the following spring application context:

<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
      <props>
        <!--
             <prop key="hibernate.dialect">${hibernate.dialect}</prop>
          -->
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>

            <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
            <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
            <prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>

            <prop key="hibernate.connection.pool_size">10</prop>
            <prop key="hibernate.jdbc.batch_size">1000</prop>
            <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>

        </props>
    </property>
    <property name="annotatedClasses">
        <list>
          ...
       </list>
    </property>

    <property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
</bean>

Then problem is: Although Hibernate should support Dialect-Autodetection this code doesnt work: Uppon Application-Init the following exception is thrown:

org.hibernate.HibernateException: The dialect was not set. Set the property hibernate.dialect.
    at org.hibernate.dialect.Dialect.instantiateDialect(Dialect.java:256)
    at org.hibernate.dialect.Dialect.getDialect(Dialect.java:234)
    at org.hibernate.dialect.Dialect.getDialect(Dialect.java:249)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean$3.doInHibernate(LocalSessionFactoryBean.java:957)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
    at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.updateDatabaseSchema(LocalSessionFactoryBean.java:953)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.afterSessionFactoryCreation(LocalSessionFactoryBean.java:843)
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:213)

I can avoid this exception by uncommenting the hibernate.dialect property. Why do I have to do this? Why cant hibernate just autodetect the dialect like it is supposed to?

I want do remove the dialect-property to solve this problem.

Answer

ChssPly76 picture ChssPly76 · Oct 6, 2009

Hibernate itself tries to auto-detect dialect during Configuration.buildSessioNFactory() call - and usually, though not always, succeeds.

Spring code, however, does not - and that's where you get the exception. LocalSessionFactoryBean.updateDatabaseSchema() method uses Dialect.getDialect() method to obtain Dialect instance which requires dialect to be explicitly set.

I'm not quite sure why it's done that way, though I suspect it's a precaution against Hibernate mistakenly detecting your dialect incorrectly and messing up your database as a result (since updating schema can potentially be quite disastrous).

Your options are:

  1. Explicitly specifying dialect
  2. Setting schemaUpdate to false
  3. Extending LocalSessionFactoryBean and overriding updateDatabaseSchema() method to take the (already auto-detected) dialect from session factory instance.

You'll have to class cast it to SessionFactoryImplementor for that:

public void updateDatabaseSchema() throws DataAccessException {
  final Dialect dialect = ((SessionFactoryImplementor) getSessionFactory()).getDialect();
  ...
  hibernateTemplate.execute(new HibernateCallback() {
    ...
    // you already have the dialect so you don't need to get it using this:
    // Dialect dialect = Dialect.getDialect(getConfiguration().getProperties());
    ...
  );
}