java.lang.IllegalStateException: No value for key [org.hibernate.impl.SessionFactoryImpl] with AOP
As @kriegaex said, the problem comes from the fact I'm using the same session to do the find and update operations.
Given that information, I use this following workaround (which works): I use two separate sessions, one for find and the other for 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;
}
}
With this solution, there is no need to close the session in my advice code anymore.
NB: I'm opening a stateless session because in my project FooService.update also calls FooService.find in order to set some attributes, so I do not want to have the modifications in my advice code.
l-lin
Passionate Senior Web Developer specializing in back end development, especially in Java and Spring Framework. Strong background and experience in all stages of the development cycle, from code, to build, to deploy in production. Coding best practice evangelist and passionate developer who loves all things in software and the web in general with particular interest in: Java, Go, Docker.
Updated on June 05, 2022Comments
-
l-lin almost 2 years
I'm having an error each time I update an entity using Hibernate. Here's my story:
I have a service with an annotation @Transactional and is calling a DAO.update method.
@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); } }
I have an AOP which catch the DAO.update in order to make some operations.
@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; } }
However, after updating the entity (fooDAO.update(foo)), I get the following error:
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]
This error is not blocking (the update still goes through). But I want to correct this error. Do you have any idea how I can do that?
I think the error comes from the fact I closed the session. But I have to close it in order to update the entity.