【问题标题】:Spring Boot - Handle to Hibernate SessionFactorySpring Boot - Hibernate SessionFactory 的句柄
【发布时间】:2014-09-23 16:46:22
【问题描述】:

有谁知道如何获取 Spring Boot 创建的 Hibernate SessionFactory 的句柄?

【问题讨论】:

  • AFAIK Spring Boot 不会自动配置 Hibernate SessionFactory。它创建一个 JPA EntityManagerFactory

标签: java spring hibernate spring-boot


【解决方案1】:

您可以通过以下方式完成此操作:

SessionFactory sessionFactory = 
    entityManagerFactory.unwrap(SessionFactory.class);

其中 entityManagerFactory 是一个 JPA EntityManagerFactory

package net.andreaskluth.hibernatesample;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SomeService {

  private SessionFactory hibernateFactory;

  @Autowired
  public SomeService(EntityManagerFactory factory) {
    if(factory.unwrap(SessionFactory.class) == null){
      throw new NullPointerException("factory is not a hibernate factory");
    }
    this.hibernateFactory = factory.unwrap(SessionFactory.class);
  }

}

【讨论】:

  • 如果您将SessionFactory 的创建移动到Spring @Configuration 并使用@Bean 方法来创建它可能会更好。
  • @geoand 这里没有创建任何内容:-)。访问底层SessionFactory 应该是一种特殊情况(例如配置目的),因此并不简单。如果访问休眠基础设施很容易,您必须应对习惯于休眠访问SessionFactory 而不是EntityManagerFactory 的开发人员。
  • 我的意思是,如果在多个地方都需要它,最好有一个 SessionFactory 类型的 bean(使用与您类似的代码创建)
  • @geoand 由于 Hibernate 5.2 SessionFactory 扩展了 EntityManagerFactory。如果按 EntityManagerFactory 类型绑定,您会考虑问题。
  • 对于社区,我在@Bean 中使用该代码,以下是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!
【解决方案2】:

自动装配 Hibernate SessionFactory 的最简单且最简洁的方法是:

这是 Spring Boot 1.x 与 Hibernate 4 的解决方案:

application.properties:

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

配置类:

@Bean
public HibernateJpaSessionFactoryBean sessionFactory() {
    return new HibernateJpaSessionFactoryBean();
}

然后你可以像往常一样在你的服务中自动连接SessionFactory

@Autowired
private SessionFactory sessionFactory;

从带有 Hibernate 5 的 Spring Boot 1.5 开始,现在这是首选方式:

application.properties:

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

配置类:

@EnableAutoConfiguration
...
...
@Bean
public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory emf) {
    HibernateJpaSessionFactoryBean fact = new HibernateJpaSessionFactoryBean();
    fact.setEntityManagerFactory(emf);
    return fact;
}

【讨论】:

  • 作为一个额外的说明,作为配置调用提到的是你@SpringBootApplication 你的应用程序。您可以将此方法粘贴在 main 方法上方。
  • 有什么方法可以在这里获取 SessionFactoryBean 吗?我需要从休眠配置访问休眠映射
  • 哦,没关系,我知道我可以将 SessionFactory 转换为 Mapping 并且它可以工作
  • 我的 sessionFactory 返回 null。有什么建议吗?
  • HibernateJpaSessionFactoryBean 现已弃用
【解决方案3】:

伟大的工作安德烈亚斯。我创建了一个 bean 版本,以便可以自动装配 SessionFactory。

import javax.persistence.EntityManagerFactory;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

....

@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);
}

【讨论】:

  • 我在哪里创建了这个 bean?
  • 哪里需要 SessionFactory :) 你能把你的问题说得更清楚吗?
  • 正如 Andreas 的回答所示,只需将此代码添加到 @Component 类,它本质上是一个服务类。它去哪里并不重要 - Spring 连接的任何组件。通过这种方式,您可以将其包含在@Autowired private SessionFactory sessionFactory 中并使用它。
  • 谢谢,如何使用这个 sessionFactory 创建一个新会话?
  • @obesechicken13 作为最佳实践,可以在 @Configuration 类中定义此类 @Bean 定义
【解决方案4】:

它适用于 Spring Boot 2.1.0 和 Hibernate 5

@PersistenceContext
private EntityManager entityManager;

然后你可以使用 entityManager.unwrap(Session.class) 来创建新的 Session

Session session = null;
if (entityManager == null
    || (session = entityManager.unwrap(Session.class)) == null) {

    throw new NullPointerException();
}

示例创建查询:

session.createQuery("FROM Student");

application.properties:

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:db11g
spring.datasource.username=admin
spring.datasource.password=admin
spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect

【讨论】:

  • 实际上 EntityManager 本身提供了所需的方法,例如; createQuery 等。如果您深入研究这些方法的实现。 entityManager 本身将请求移交给 Session 实现类。因此,我遵循特定的版本。 Hibernate 的家伙故意使访问会话变得困难,但使用实体管理器进行会话操作。我阅读了一些关于此的内容,但无法直接找到。
  • 感谢样本 - 唯一一个能够获得有效(且未弃用)会话的样本! (在 Spring Boot 2.2 和 Hibernate5 中)
【解决方案5】:

另一种类似于yglodt的方式

在 application.properties 中:

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

在你的配置类中:

@Bean
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
    return hemf.getSessionFactory();
}

然后你可以像往常一样在你的服务中自动装配 SessionFactory:

@Autowired
private SessionFactory sessionFactory;

【讨论】:

  • 有什么方法可以在这里获取 SessionFactoryBean 吗?我需要从休眠配置访问休眠映射
  • 另外,这种方法不适用于我最新的 spring boot,说没有可用的 HibernateEntityManagerFactory 实例
  • 没关系,我可以看到我可以将 SessionFactory 转换为 Mapping
  • HibernateEntityManagerFactory 现已弃用。
【解决方案6】:

如果确实需要通过@Autowire 访问SessionFactory,我宁愿配置另一个EntityManagerFactory,然后用它来配置SessionFactory bean,如下所示:

@Configuration
public class SessionFactoryConfig {

@Autowired 
DataSource dataSource;

@Autowired
JpaVendorAdapter jpaVendorAdapter;

@Bean
@Primary
public EntityManagerFactory entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setDataSource(dataSource);
    emf.setJpaVendorAdapter(jpaVendorAdapter);
    emf.setPackagesToScan("com.hibernateLearning");
    emf.setPersistenceUnitName("default");
    emf.afterPropertiesSet();
    return emf.getObject();
}

@Bean
public SessionFactory setSessionFactory(EntityManagerFactory entityManagerFactory) {
    return entityManagerFactory.unwrap(SessionFactory.class);
} }

【讨论】:

    【解决方案7】:

    SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);

    entityManagerFactory 是一个 JPA EntityManagerFactory

    【讨论】:

    • 这会复制接受的答案。当您发布答案时,应该是因为您有一些东西可以回答问题但没有被任何现有答案所涵盖。
    猜你喜欢
    • 2018-03-22
    • 2018-07-25
    • 1970-01-01
    • 2011-12-28
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    相关资源
    最近更新 更多