Configure sessionFactory with Spring, Hibernate and LocalSessionFactoryBuilder

耗尽温柔 提交于 2019-11-30 14:51:21

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!