Hibernate5 SessionImpl无法识别JpaTransactionManager启动的事务

时间:2018-08-09 14:44:12

标签: spring hibernate spring-data-jpa spring-transactions

Hibernate5 SessionImpl无法识别JpaTransactionManager启动的事务

我最近将旧版Java Web应用程序迁移到了Spring-boot Hibernate。球衣已在旧版应用中使用,因此继续使用spring-boot-starter-jersey。所以堆栈是:

RestfulService(Jersey)-> Spring Service-> Hibernate DAO(旧版代码)。

Spring服务和Hibernate DAO都通过各自的公共接口使用,并且在实现类的公共方法上具有@Transactional。

休眠DAO看起来像:

@存储库 公共类UserDaoImpl实现UserDao {

@Autowired
@Qualifier("entityManagerFactory")
EntityManagerFactory entityManagerFactory;

public SessionFactory getSessionFactory() {
    return entityManagerFactory.unwrap(SessionFactory.class);
}

@Override
public User getUserByUserName(String userName) throws Exception {

    User user = null;
    Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(User.class);
    criteria.add(Restrictions.eq("userName", userName));
    user = (User) criteria.uniqueResult();
    return user;
}

}

使用 JpaTransactionManager 时出现异常:

javax.persistence.TransactionRequiredException: no transaction is in progress.

javax.persistence.TransactionRequiredException: no transaction is in progress
    at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3505)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1427)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423)
    at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:147)
    at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
    at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:96)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:922)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:730)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.iotu.serviceImpl.UserServiceImpl$$EnhancerBySpringCGLIB$$d0c10f8c.checkLoginDetails(<generated>)
    at com.iotu.webservices.UserWS.userAuthentication(UserWS.java:1467)
    at com.iotu.webservices.UserWS$$FastClassBySpringCGLIB$$66e6577d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
    at com.iotu.webservices.UserWS$$EnhancerBySpringCGLIB$$99ca5efe.userAuthentication(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:76)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:148)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:191)

切换到 HibernateTransactionManager ,Hibernate能够识别正在进行的事务。没有异常。

@Configuration
@EnableJpaRepositories("com.app.repository")
public class AppConfiguration {

   @Bean
   public HibernateTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
       SessionFactory sf = entityManagerFactory.unwrap(SessionFactory.class);
      return new HibernateTransactionManager(sf);
   }

但是它有缺点。对于较新的功能,我正在使用spring数据存储库。使用HibernateTransactionManager,JpaRepository的save方法不适用于实体。它不会触发更新sql(控制台上没有错误)。 findXX方法工作正常。

@Repository
public interface LessonCategoryRepository extends JpaRepository<LessonCategory, Long> {

   public List<LessonCategory> findByCategoryAndLanguage(@Param("category") String category, @Param("language") String language);
} 

当我切换到JpaTransactionManager时,通过JpaRepository进行的更新工作正常,但开始获取javax.persistence.TransactionRequiredException:使用遗留DAO类的服务调用未进行任何事务。

总结:

  • 使用HibernateTransactionManager:Hibernate5可以识别当前事务,但JpaRepository不会持久存储数据。
  • 使用JpaTransactionManager:Hibernate5会话无法识别当前事务,但JpaRepository正在保留数据。

我可以使JpaTransactionManager与现有的休眠DAO类一起使用吗?要么 我可以使HibernateTransactionManager与JpaRepository一起使用吗? ..这样我就可以按原样使用旧版DAO类,但可以继续使用JpaRepositories。

0 个答案:

没有答案