Java.lang.IllegalStateException: Aucune valeur pour la clé [org.hiberner.impl.SessionFactoryImpl] avec AOP


J'ai une erreur chaque fois que je mets à jour une entité en utilisant Hibernate. Voici mon histoire:

J'ai un service avec une annotation @Transactional et appelle un DAO.méthode de mise à jour.

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

J'ai un AOP qui attrape le DAO.mise à jour afin de faire quelques opérations.

@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;
   }
}

Cependant, après la mise à jour de l'entité (fooDAO.mise à jour(foo)), j'obtiens l'erreur suivante:

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]

Cette erreur ne bloque pas (la mise à jour continue). Mais je veux corrigez cette erreur. Avez-vous une idée de comment je peux faire?

, je pense que l'erreur vient du fait que j'ai fermé la session. Mais je dois le fermer afin de mettre à jour l'entité.

Author: kriegaex, 2014-05-12

1 answers

Comme l'a dit @kriegaex, le problème vient du fait que j'utilise la même session pour effectuer les opérations findet update.

Compte tenu de cette information, j'utilise cette solution de contournement suivante (qui fonctionne): j'utilise deux sessions distinctes, l'une pour les trouver et l'autre pour mise à jour.

@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;
    }
}

Avec cette solution, il n'est plus nécessaire de fermer la session dans mon code de conseil.

NB: J'ouvre une session sans état car dans mon projet FooService.update appelle également FooService.find afin de définir certains attributs, donc je ne veux pas avoir les modifications dans mon code de conseil.

 1
Author: l-lin, 2014-05-12 12:57:44