【发布时间】:2014-05-18 12:50:02
【问题描述】:
多年来,我使用标准 LocalSessionFactoryBeanSolution 使用 Spring (3.2.x) + Hibernate (3.6.10) 开发了一个相当大的项目。
最近我想通过 hibernate 切换到 JPA,以便能够使用 Spring Data JPA 功能。这是所有南下的时刻。事实证明,基于 HibernateTemplate 的类和基于 EntityManager 的类的 Hibernate 会话分辨率不同。我无法将我所有的 hibernate+hibernatetemplate 代码迁移到 JPA - 这简直是太多的工作。
由于一个测试用例超过1000字,简单地说这个测试用例失败了:
@Test
@Transactional
public void test0() {
HibernateTemplate template = new HibernateTemplate( sessionFactory );
User user = template.execute( new HibernateCallback<User>() {
@Override
public User doInHibernate( Session session ) throws HibernateException, SQLException {
return (User) session.load( User.class,
1l );
}
} );
Session session = entityManager.unwrap( Session.class );
Assert.assertTrue( session.contains( user ) );
}
我唯一能做的就是加入一些“AspectJ 魔法”。我设法使这一切都与这方面有关:
@Aspect
public class Hibernate2JpaMigrationFixes {
@SuppressWarnings("unused")
private final static Logger log = LoggerFactory.getLogger( Hibernate2JpaMigrationFixes.class );
@PersistenceContext
private EntityManager entityManager;
@Around("execution( * org.springframework.orm.hibernate3.HibernateTemplate.isAllowCreate())")
public Object disallowHibernateSessionCreation( ProceedingJoinPoint pjp ) {
return Boolean.FALSE;
}
@Around("execution( * org.springframework.orm.hibernate3.HibernateTemplate.clear())")
public void disallowClear( ProceedingJoinPoint pjp ) {
throw new RuntimeException( "clear not allowed" );
}
@Around("execution( * org.springframework.orm.hibernate3.HibernateTemplate.getSession())")
public Object useTheSameSessionEntityManagerDoes( ProceedingJoinPoint pjp ) {
return entityManager.unwrap( Session.class );
}
}
我也尝试过修改 hibernate.current_session_context_class - 类被实例化 - 仍然从未用于解析当前会话。
我的 spring + hibernate 配置如下:
<bean id="pum" class="org.springframework.data.jpa.support.MergingPersistenceUnitManager">
<property name="packagesToScan" value="com.xxx.persistence,com.xxx.smart,com.xxx.clientapp.server.model" />
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="persistenceUnitManager" ref="pum" />
<property name="jpaPropertyMap">
<map>
<entry key="javax.persistence.validation.factory" value-ref="validator" />
<entry key="hibernate.dialect" value="${hibernate.dialect}" />
<entry key="hibernate.show_sql" value="${hibernate.show_sql}" />
<entry key="hibernate.ejb.naming_strategy" value="com.mobilebox.persistence.hibernate.CustomNamingStrategy" />
<!--
<entry key="hibernate.current_session_context_class" value="org.springframework.orm.hibernate3.SpringSessionContext" />
-->
</map>
</property>
</bean>
<!-- transaction management -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"
p:jpaDialect-ref="jpaDialect" />
<!-- legacy -->
<bean id="sessionFactory" class="org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean" />
<bean id="baseHibernateDao" abstract="true" p:sessionFactory-ref="sessionFactory" />
<!-- nowe dao -->
<jpa:repositories base-package="com.xxx.smart.dao" />
<jpa:repositories base-package="com.xxx.smart.repository" />
它仍然只是觉得我错过了一些东西。如果没有这种黑客行为,我能做些什么吗?
【问题讨论】:
-
我已经发布了一些可能的原因,如果您可以尝试一下并回复发生的情况(重要:如果太大,请发布完整的堆栈跟踪,并带有指向 pastebin.com 的链接)
-
Spring 默认将
hibernate.current_session_context_class设置为 Spring 类。如果您有 persistence.xml 文件,请发布。基本上你的配置应该可以工作。另请注意,session.load并没有做太多,它只是构建一个代理,而session.get实际上是从数据库中检索元素!。