web-dev-qa-db-ja.com

HibernateとSpringのデータJPAの同時使用?

Spring Data JPA(JPAプロバイダーとしてHibernateが支援)を使用して、同時にHibernateを直接使用することは可能ですか?

問題は、JpaTransactionManagerを使用すると、org.hibernate.HibernateException: No Session found for current threadで現在のセッションを取得できないことです。 HibernateTransactionマネージャーに切り替えると、JPAリポジトリは変更をコミットできません。

ここに私の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"/>

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

Springデータリポジトリ定義の例:

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

ソフトウェアのバージョン:

<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>

ですから、質問は-同じトランザクション(@Transactionalアノテーションで指定)でSpring JPAリポジトリと直接のHibernate呼び出しの両方を使用することは可能ですか?

32
akashihi

SessionFactoryを作成する代わりに、EntityManager.unwrap(Session.class)を使用してHibernate Sessionを取得し、Sessionオブジェクトからセッションファクトリを取得します。

EntityManagerFactory.unwrap(SessionFactory.class)を使用して、Hibernate SessionFactoryを直接取得することもできます。

20
neildo

現在、HibernateとJPAの両方を構成する単一の構成方法が必要です。設定にはJPAを使用する必要があるため、休止状態のセットアップを削除してください。

Hibernate4を使用しているため、あまり知られていませんが、SpringのHibernateJpaSessionFactoryBeanを利用できます。 SessionFactory(必要だと思います)へのアクセスが必要な場合。

適用すると、構成は次のようになります。

<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>

プレーンJPA APIを使用するようにアプリケーションをリファクタリングしているときにのみ、これを中間ソリューションとして使用することをお勧めします。両方の戦略を混ぜることはお勧めしません。

25
M. Deinum

これは私がやったことであり、うまく機能しました:1つのデータソース、2つのトランザクションマネージャー。
データソースBean:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!-- bulabula... -->
</bean>

Hibernate XMLベースの構成の場合:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingLocations" value="#{propertyUtils.getList('hibernate.hbm')}"/>
    <property name="hibernateProperties">
        <value>
            <!-- bulabulabula... -->
        </value>
    </property>
</bean>

<bean id="transactionManager" primary="true" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

また、spring-data-jpa Javaベースの構成:

@Configuration
@EnableJpaRepositories(basePackages = {"org.sharder.core.repository"}, 
transactionManagerRef = "jpaTransactionManager")
@EnableTransactionManagement
public class JpaConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ComboPooledDataSource comboPooledDataSource) {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("org.sharder.core.entity");
    factory.setDataSource(comboPooledDataSource);
    factory.setJpaProperties(getHibernateProperties());
    return factory;
}

@Bean(name = "jpaTransactionManager")
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory);
    return txManager;
}

private Properties getHibernateProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
    properties.setProperty("hibernate.cache.use_query_cache", "true");
    properties.setProperty("hibernate.cache.use_second_level_cache", "true");
    properties.setProperty("hibernate.cache.use_structured_entries", "true");
    properties.setProperty("hibernate.format_sql", "true");
    properties.setProperty("hibernate.show_sql", "true");
    properties.setProperty("hibernate.use_sql_comments", "true");
    properties.setProperty("hibernate.query.substitutions", "true 1, false 0");
    properties.setProperty("hibernate.jdbc.fetch_size", "20");
    properties.setProperty("hibernate.connection.autocommit", "false");
    properties.setProperty("hibernate.connection.release_mode", "auto");
    return properties;
}

}

transactionManagerRef = "jpaTransactionManager" JpaTransactionManagerがリポジトリで使用されるように設定します。 Spring Data JPA名前空間の属性

1
CloudSen