简体   繁体   中英

Configure sessionFactory with Spring, Hibernate and LocalSessionFactoryBuilder

I'm trying to create sessionFactory bean using spring 3.2 and hibernate 4. I used the following code for that. But the problem is buildSessionFactory() is deprecated and the buildSessionFactory(ServiceRegistry serviceRegistry) is suggested to use instead in javadoc. However, I'm not being able to understand what is ServiceRegistry and how to use buildSessionFactory(ServiceRegistry serviceRegistry) .


@Configuration
public class AppConfig {

    ...


    @Bean
    public SessionFactory sessionFactory() {
    return new LocalSessionFactoryBuilder(dataSource())
        .scanPackages("com.mypackages")
        .addProperties(hibernateProperties())
        
  
 
  
  
  
    .buildSessionFactory(); 
  

    }
}

ServiceRegistry interface is related to concept of services (that is new for Hibernate 4). Services are classes that provide Hibernate with various functionality and for which user can plug in alternate implementations. See this wiki page for details.

You are right that method buildSessionFactory() is deprecated in Hibernate's Configuration class in favor of method buildSessionFactory(ServiceRegistry serviceRegistry) . In a pure Hibernate's environment (without Spring) it is supposed that you will initialize instance of ServiceRegistry in such a way:

private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;

private static SessionFactory configureSessionFactory() throws HibernateException {
    Configuration configuration = new Configuration();
    configuration.configure();

    serviceRegistry = new ServiceRegistryBuilder()
             .applySettings(configuration.getProperties())
             .buildServiceRegistry();

    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    return sessionFactory;
}

But by now the deprecated method buildSessionFactory() also does the same initialization of ServiceRegistry for you.

Spring's LocalSessionFactoryBuilder class is just the extension of Hibernate's Configuration class. But since all the specific work of Spring is done in overriden method LocalSessionFactoryBuilder.buildSessionFactory() you can't use method buildSessionFactory(ServiceRegistry serviceRegistry) in Spring's environment. Nothing much 'cause it's ok to use buildSessionFactory() that does exactly the same work. So let's just annotate the method in AppConfig with @SuppressWarnings("deprecation") and patiently wait for Spring to provide better integration with Hibernate 4.

You could also write the code without chaining:

LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("com.mypackages");
builder.addProperties(hibernateProperties());
return builder.buildSessionFactory();

Slightly more verbose but not as smelly as @SuppressWarnings("deprecation")

The answer supplied by Artem Shafranov is not entirely correct and you might run into a very confusing issue as I did.

If you use

hibernate.hbm2ddl.auto

your application will not start up because the connection pool in hbm2dll will be set to UserSuppliedConnectionProviderImpl (basically a nice way to say: null). You will see this exception:

org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]

The reason for this has to do with the ServiceRegistry which is used by hbm2dll but which doesn't play nice with Spring. Using many of the suggested programmatic session configuration methods it will not yet have the proper reference when hbm2dll is executed.

The only way that worked for me is the following

@Inject
DataSource datasource;

@Bean
@SuppressWarnings("deprecation")
public SessionFactory sessionFactory() throws IOException{

    LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
    sessionFactoryBean.setPackagesToScan("nl.your.model");
    sessionFactoryBean.setHibernateProperties(hibernateProperties());
    sessionFactoryBean.setDataSource(datasource);
    sessionFactoryBean.afterPropertiesSet();

    return sessionFactoryBean.getObject();
}

Using LocalSessionFactoryBuilder failed. Using StandardServiceRegistryBuilder, suprisingly, failed also.

Really confusing issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM