同时使用Hibernate和Spring数据jpa?

时间:2022-09-11 16:44:49

Is it possible to use Spring Data JPA (backed by Hibernate as JPA provider) and directly use Hibernate at the same time?

是否可以使用Spring Data JPA(由Hibernate作为JPA提供程序支持)并同时直接使用Hibernate?

The problem is that when i use JpaTransactionManager, i'm not able to retrieve current session with org.hibernate.HibernateException: No Session found for current thread. When i switch to HibernateTransaction manager, JPA repositories are not able to commit changes.

问题是,当我使用JpaTransactionManager时,我无法使用org.hibernate.HibernateException检索当前会话:找不到当前线程的会话。当我切换到HibernateTransaction管理器时,JPA存储库无法提交更改。

Here is the part of my Spring context (with that context i'm not able to use direct Hibernate calls):

这是我的Spring上下文的一部分(使用该上下文我不能使用直接的Hibernate调用):

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/IPGCONF"/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
      p:dataSource-ref="dataSource">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

<jpa:repositories base-package="com.satgate"/>

Example of hibernate repository:

hibernate存储库的示例:

public Collection<Layer> listCurrent(Carrier carrier) {
    Criteria query = sessionFactory.getCurrentSession()
                    .createCriteria(Layer.class)
                    .add(Restrictions.eq("carrier", carrier));
    query.createCriteria("bitrate")
            .addOrder(Order.desc("bitrate"))
            .add(Restrictions.eq("symbolrate", carrier.getSymbolrate()));
    return query.list();
}

Example of Spring data repository definition:

Spring数据存储库定义的示例:

public interface BitrateRepository extends PagingAndSortingRepository<Bitrate, Long> { }

Software versions:

软件版本:

<org.springframework.version>4.0.0.RELEASE</org.springframework.version>
<org.springframework.data.version>1.4.3.RELEASE</org.springframework.data.version>
<hibernate.version>4.3.0.Final</hibernate.version>

So, the question is - is it possible to use in the same transaction (specified by @Transactional annotation) both Spring JPA repositories and direct Hibernate calls and how to achieve that?

所以,问题是 - 是否可以在同一个事务中使用(由@Transactional注释指定)Spring JPA存储库和直接Hibernate调用以及如何实现它?

2 个解决方案

#1


19  

Instead of creating a SessionFactory, use EntityManager.unwrap(Session.class) to get a Hibernate Session and retrieve the session factory from the Session object.

而不是创建SessionFactory,使用EntityManager.unwrap(Session.class)来获取Hibernate会话并从Session对象中检索会话工厂。

You can also use EntityManagerFactory.unwrap(SessionFactory.class) to get the Hibernate SessionFactory directly.

您还可以使用EntityManagerFactory.unwrap(SessionFactory.class)直接获取Hibernate SessionFactory。

#2


22  

You need a single way of configuration you are now configuring both Hibernate and JPA. You should be using JPA for configuration so remove the hibernate setup.

您需要一种配置方式,现在正在配置Hibernate和JPA。您应该使用JPA进行配置,因此请删除hibernate设置。

You are using Hibernate4 so you can take advantage of the, not so well known, HibernateJpaSessionFactoryBean of Spring. If you need access to the SessionFactory (which I assume you need).

您正在使用Hibernate4,因此您可以利用Spring的HibernateJpaSessionFactoryBean,而不是那么着名。如果您需要访问SessionFactory(我假设您需要)。

When applied your configuration will like something like this.

应用后,您的配置会像这样。

<bean id="sessionFactory" class="org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

I would suggest to only use this as an intermediate solution while you are refactoring your applicaiton to use the plain JPA api. I wouldn't suggest mixing both strategies.

我建议只使用它作为中间解决方案,同时重构您的应用程序以使用普通的JPA api。我不建议混合两种策略。

#1


19  

Instead of creating a SessionFactory, use EntityManager.unwrap(Session.class) to get a Hibernate Session and retrieve the session factory from the Session object.

而不是创建SessionFactory,使用EntityManager.unwrap(Session.class)来获取Hibernate会话并从Session对象中检索会话工厂。

You can also use EntityManagerFactory.unwrap(SessionFactory.class) to get the Hibernate SessionFactory directly.

您还可以使用EntityManagerFactory.unwrap(SessionFactory.class)直接获取Hibernate SessionFactory。

#2


22  

You need a single way of configuration you are now configuring both Hibernate and JPA. You should be using JPA for configuration so remove the hibernate setup.

您需要一种配置方式,现在正在配置Hibernate和JPA。您应该使用JPA进行配置,因此请删除hibernate设置。

You are using Hibernate4 so you can take advantage of the, not so well known, HibernateJpaSessionFactoryBean of Spring. If you need access to the SessionFactory (which I assume you need).

您正在使用Hibernate4,因此您可以利用Spring的HibernateJpaSessionFactoryBean,而不是那么着名。如果您需要访问SessionFactory(我假设您需要)。

When applied your configuration will like something like this.

应用后,您的配置会像这样。

<bean id="sessionFactory" class="org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

I would suggest to only use this as an intermediate solution while you are refactoring your applicaiton to use the plain JPA api. I wouldn't suggest mixing both strategies.

我建议只使用它作为中间解决方案,同时重构您的应用程序以使用普通的JPA api。我不建议混合两种策略。