【问题标题】:java.lang.IllegalStateException: No value for key [org.hibernate.impl.SessionFactoryImpl] with AOPjava.lang.IllegalStateException:使用 AOP 的键 [org.hibernate.impl.SessionFactoryImpl] 没有值
【发布时间】:2014-05-12 20:57:44
【问题描述】:

每次使用 Hibernate 更新实体时都会出错。 这是我的故事:

我有一个带有 @Transactional 注释的服务,并且正在调用 DAO.update 方法。

@Service
@Transactional
public class FooServiceImpl implements FooService {
    @Inject
    private FooDAO fooDAO;

    @Override
    public Foo update(Foo foo) {
       return fooDAO.update(foo);
    }

    @Override
    public Foo find(int fooId) {
       return fooDAO.findById(fooId);
    }
}

我有一个 AOP,它捕获 DAO.update 以便进行一些操作。

@Aspect
@Order(2)
@Component
public class FooTackerAspect {
   @Inject
   private FooService fooService;

   @Inject
   private SessionFactoryManager sessionFactoryManager;

   @Pointcut("execution(* com.foo.bar.FooService.update(..))")
   public void methodToTrack() {}

   @Around("methodToTrack")
   public Object track(final ProceedingJoinPoint joinPoint) throws Throwable {
      int fooId = fetchIdFromJoinPoint(joinPoint);
      Foo foo = fooService.find(fooId);

      // Do some operations

      // I close the session in order to avoid the exception
      // org.hibernate.NonUniqueObjectException: a different object with
      // the same identifier value was already associated with the session
      sessionFactoryManager.getSessionFactory(DataSource.FOO)
          .getCurrentSession().close();

      Object retVal = joinPoint.proceed();
      return retVal;
   }
}

但是,在更新实体 (fooDAO.update(foo)) 后,我收到以下错误:

2056953 [http-bio-8080-exec-4] ERROR o.s.t.s.TransactionSynchronizationUtils - TransactionSynchronization.beforeCompletion threw exception 
java.lang.IllegalStateException: No value for key [org.hibernate.impl.SessionFactoryImpl@762d6271] bound to thread [http-bio-8080-exec-4]
    at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:209) ~[spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCompletion(SpringSessionSynchronization.java:193) ~[spring-orm-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCompletion(TransactionSynchronizationUtils.java:106) ~[spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(AbstractPlatformTransactionManager.java:938) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:739) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) [spring-tx-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) [spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
    at com.sun.proxy.$Proxy112.update(Unknown Source) [$Proxy112.class:na]

此错误未阻塞(更新仍在进行)。但我想纠正这个错误。 你知道我该怎么做吗?

我认为错误来自我关闭会话的事实。但我必须关闭它才能更新实体。

【问题讨论】:

  • 先关闭会话然后再调用FooServiceImpl.update() 听起来并不健康,因为这正是proceed() 所做的。我建议您修复您的建议代码。也许您希望通过关闭会话来避免的另一个异常是由于您在代码中所做的事情没有向我们披露,而是被注释“做一些操作”所取代。

标签: java spring hibernate aop


【解决方案1】:

正如@kriegaex 所说,问题在于我使用同一个会话来执行 findupdate 操作。

鉴于该信息,我使用以下解决方法(可行):我使用两个单独的会话,一个用于 find,另一个用于 update

@Repository
public class FooDAOImpl implements FooDAO {
    private FooHibernateDaoSupport hibernateDaoSupport;

    public FooDAOImpl() {
        // Init DaoSupport
    }

    @Override
    public Foo findById(final Serializable fooId) {
        StatelessSession session = hibernateDaoSupport.getSessionFactory().openStatelessSession();
        Foo foo = (Foo) session.get(Foo.class, fooId);
        session.close;
        return foo;
    }

    @Override
    public Foo update(Foo foo) {
        getHibernateTemplate().update(entity);
        return entity;
    }
}

有了这个解决方案,我的建议代码中不再需要关闭会话了。

NB:我正在打开一个无状态会话,因为在我的项目中 FooService.update 还调用 FooService.find 以设置一些属性,所以我不想在我的建议代码中进行修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    相关资源
    最近更新 更多