Org.hibernate.HibernateException: saving is not valid without an active transaction in my case

I have a GenericService class that 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); } ........................... } 

The AnswerService class extends the GenericService . It automatically executes AnswerDao and declares itself as a component of @Service and @Transactional spring.

 @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 the save method.

 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 the save method on the GenericService , I expect spring to create a transaction for the hibernation session, but the transaction will not be created, and I get this error directly in the GenericDaoHibernate.save method:

 org.hibernate.HibernateException: save is not valid without active transaction 

My spring configuration file for the service level:

 <!-- 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" /> 

Therefore, when I do not rely on spring @Transactional support and start / commit transaction org.hibernate.Session , then everything is fine and I have no error.

Why doesn't spring provide a transaction for methods called GenericSerice?

BTW, GenericService and AnswerService do not have interfaces.

EDIT . This is the transaction returned by the 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 that didn't help.

+6
source share
5 answers

I donโ€™t know the root cause, but removing this property from my hibernation configuration resolved the issue for me.

 <prop key="hibernate.current_session_context_class">thread</prop> 

Found on this forum

+7
source

getCurrentSession() : Gets the current session.

Creates a new session other than a context session

openSession() : Returns: The created session.

+1
source

I 'using org.springframework.orm.jpa.JpaTransactionManager for my TransactionManager and Hibernate adapter in my noun. manManager.

  <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <property name="packagesToScan" value="domain"/> <property name="jpaPropertyMap"> <map> <entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> <entry key="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" /> <entry key="hibernate.show_sql" value="false" /> <entry key="hibernate.multiTenancy" value="SCHEMA" /> <entry key="hibernate.multi_tenant_connection_provider" value-ref="mySQLMultiTenantConnectionProvider" /> <entry key="hibernate.tenant_identifier_resolver" value-ref="tenantIdentifierResolver" /> </map> </property> </bean> 

I suggest changes to this configuration.

But if you donโ€™t, try debugging in the HibernateTransactionManager in the doGetTransaction method and see what happens.

0
source

You should talk about what methods or classes need transnational support from Spring. @Transnational Annotation (can be specified at the method or class level) guarantees transnational behavior for annotated methods and classes, but not for the entire application.

0
source

Add @Transactional notes to your dao methods.

-1
source

Source: https://habr.com/ru/post/971524/


All Articles