提问者:小点点

为Hibernate 5正确完整地配置Spring Boot 1.5. x


关于1.5.10版本的Spring Boot。RELEASE版本。它在内部与版本的Hibernate一起工作5.0.12.Final

目的是避免以下错误消息:

required a bean of type 'org.hibernate.SessionFactory' that could not be found

应该应用HibernateJpaSessionFactoryBean类。它来自:

  • 需要一个找不到的类型为“org. hibernate.SessionFactory”的bean

这里的情况是HibernateJpaSessionFactoryBean类是@Deprecated

根据HibernateJpaSessionFactoryBean javadoc建议的解决方案是如何使用EntityManagerFactory#un行

因此从:

  • Spring Boot-Hibernate SessionFactory的句柄

必须手动声明以下内容:

@Bean
public SessionFactory sessionFactory(EntityManagerFactory emf) {
    return emf.unwrap(SessionFactory.class);
}

警告是强制性的在application.properties文件中包含以下内容(上面分享的帖子中没有提到):

spring.jpa.properties.hibernate.current_session_context_class = 
org.springframework.orm.hibernate5.SpringSessionContext

否则出现:

org.springframework.orm.jpa.JpaSystemException:
No CurrentSessionContext configured!; nested exception is org.hibernate.HibernateException:
No CurrentSessionContext configured!

直到这里我的@Test类通过Hibernate工作失败,这些相同的@Test类通过Spring Framework传入其他项目,因此Hibernate的所有基础设施都被手动声明。

因此通过以下代码:

@Test
public void contextLoads() {

    String[] beanNames = applicationContext.getBeanDefinitionNames();
    Arrays.sort(beanNames);
    for (String beanName : beanNames) {
        logger.info("beanName: {}", beanName);
    }

    logger.info("PlatformTransactionManager");
    if(transactionManager != null) {
        logger.info("Class: {}", transactionManager.getClass().getName());
    }

}

Spring Boot创建的所有bean都打印出来,我已确认以下内容:

 - PlatformTransactionManager 
 - Class: org.springframework.orm.jpa.JpaTransactionManager

我期望HibernateTransactionManager而不是JpaTransactionManager

我获得@Test方法通过的独特方法是再次手动声明其他@Bean

@Bean
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory){
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory);
    return transactionManager;
}

因此:

  • Hibernate 5Spring Boot 1.5. x的正确完整配置是什么?

观察:如果一切都通过application.properties文件完全配置,那就更好了(目的是避免手动声明任何@Bean

总结一下,为普通Hibernate集成Spring Boot的独特方式(考虑将通过Spring Framework工作的完整项目迁移到使用Hibernate的Spring Boot的场景)是通过以下方式:

spring.jpa.hibernate.ddl-auto = none

spring.jpa.properties.hibernate.cache.provider_class = org.hibernate.cache.NoCacheProvider
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
spring.jpa.properties.hibernate.default_batch_fetch_size = 30
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.format_sql = true
spring.jpa.properties.hibernate.jdbc.batch_size = 30
spring.jpa.properties.hibernate.max_fetch_depth = 30
spring.jpa.properties.hibernate.order_updates = true;
spring.jpa.properties.hibernate.show_sql = false
spring.jpa.properties.hibernate.use_sql_comments = true

加上这两个强制要求@Beans

@Bean
public SessionFactory sessionFactory(EntityManagerFactory emf) {
    return emf.unwrap(SessionFactory.class);
}

@Bean
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory){
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory);
    return transactionManager;
}

如果没有这两个@Beans,我已经报告了所有两个错误。

因此,目标是通过application.properties配置Hibernate


共1个答案

匿名用户

这是一个建议(Spring Boot 1.5.10. RELEASE)

文件application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/vy
spring.datasource.username=root
spring.datasource.password=123456
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

文件BeanConfig.java

package com.example;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManagerFactory;

@Configuration
public class BeanConfig {

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public SessionFactory getSessionFactory() {
        if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
            throw new NullPointerException("factory is not a hibernate factory");
        }
        return entityManagerFactory.unwrap(SessionFactory.class);
    }

}

文件UserDao.java

package com.example.dao;

import com.example.model.UserDetails;

import java.util.List;

public interface UserDao {

    List<UserDetails> getUserDetails();

}

使用SessionFactory的文件UserDaoImpl.java

package com.example.dao.impl;

import com.example.dao.UserDao;
import com.example.model.UserDetails;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    public List<UserDetails> getUserDetails() {
        Criteria criteria = sessionFactory.openSession().createCriteria(UserDetails.class);
        return criteria.list();
    }

}

目标是通过application.properties配置Hibernate

--

它不确定与HibernateORM的全部功能。