I have GenericService
class which encapsulates crud methods for subclasses:
public abstract class GenericService<D extends GenericDao<T, I>, T extends DomainObject<I>, I> {
public I save(T t) {
return getDao().save(t);
}
...........................
}
Class AnswerService
extends GenericService
. It autowires AnswerDao
and declares itself as @Service
and @Transactional
spring component.
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class AnswerService extends GenericService<AnswerDao, Answer, Long> {
@Autowired
private AnswerDao answerDao;
@Override
public void setDao(AnswerDao d) {
this.answerDao = d;
}
@Override
public AnswerDao getDao() {
return answerDao;
}
................................
}
AnswerDao
extends GenericDao
which implements method save
.
public abstract class GenericDaoHibernate<T extends DomainObject<I>, I extends Serializable> implements GenericDao<T, I> {
private Class<? extends T> entityClass;
private SessionFactory sessionFactory;
public GenericDaoHibernate(Class<? extends T> entityClass) {
this.entityClass = entityClass;
}
public GenericDaoHibernate() {
}
@Autowired
private void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
Assertor.assertNotNull(sessionFactory);
}
public Session currentSession() {
return getSessionFactory().getCurrentSession();
}
@SuppressWarnings("unchecked")
@Override
public I save(T entity) {
// Transaction transaction = currentSession().beginTransaction();
I id = (I) currentSession().save(entity);
// transaction.commit();
return id;
}
When I call save
method on GenericService
I expect spring to create transaction for hibernate Session, but transaction is not created and I get this error right in GenericDaoHibernate.save
method:
org.hibernate.HibernateException: save is not valid without active transaction
My spring config file for service layer is:
<!-- Hibernate 4 SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" p:packagesToScan="com.javahelp.domain.impl">
<property name="configLocations">
<array>
<value>classpath:META-INF/hibernate/hibernate.cfg.xml</value>
</array>
</property>
</bean>
<!-- A transaction manager for working with Hibernate session methods.
Without this transaction manager none method of hibernate session works -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- enable scanning for @Transactional annotation -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- autodetect all spring @Service beans in package com.javahelp.service
(service layer) -->
<context:component-scan base-package="com.javahelp.service" />
So when I don't rely on spring @Transactional support and begin/commit transaction by org.hibernate.Session
then all is ok and I have no error.
Why spring doesn't provide transaction for methods called on GenericSerice?
BTW, GenericService and AnswerService have no interfaces.
EDIT. This is transaction that is returned by HibernateTransactionManager.doGetTransaction
method:
txObject HibernateTransactionManager$HibernateTransactionObject (id=190)
connectionHolder null
newSession false
newSessionHolder false
previousIsolationLevel null
savepointAllowed false
sessionHolder null
I also changed my services to use interfaces but it didn't help.
Don't know the root cause, but removing the below property from my hibernate configuration solved the problem for me.
<prop key="hibernate.current_session_context_class">thread</prop>
Found on this forum
getCurrentSession()
: Obtains the current session.
Creates a new session, different from the contextual session
openSession()
: Returns: The created session.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With