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

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.

Answers


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.


I´, using org.springframework.orm.jpa.JpaTransactionManager for my TransactionManager and Hibernate adapter in my entitymanager.

       <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 to changes to this configuration.

But if you dont, try to debug in HibernateTransactionManager in the method doGetTransaction ans see what´s going on.


You should tell about which methods or classes that needs transnational support from Spring . @Transnational Annotation (can be specified on method or class level) guarantees transnational behavior for the annotated methods and classes but not to the entire application.


Add @Transactional annotations to your dao methods as well.


Need Your Help

How to use a string with redirect_to?

ruby-on-rails redirect

I'm sure this is a bone-headed question, so apologies in advance. I want to use a string with my redirect_to, like this:

Delay execution of code following UIAlertView show statement, until the alert is showing

iphone objective-c ios4 uialertview

I'm attempting to create a "Please wait" UIAlertView that will appear while my code is downloading and calculating some data, then disappear when it has finished. Specifically, it is parsing an xml...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.