0

i have a trouble opening Hibernate transaction.

This is the configuration:

    <context:annotation-config />
    <context:component-scan base-package="com.cinebot" />
    <mvc:annotation-driven />
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.cinebot.db.entity</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

<tx:annotation-driven />

And this is the faulty code:

@Transactional
public static <T> T get(Class<T> classe, Serializable id) throws Exception {
    if(id==null) return null;
    T obj = (T) HibernateUtil.getSessionFactory().getCurrentSession().get(classe, id);
    return obj;
}

This is the exception:

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

This is an example entitiy:

package com.cinebot.db.entity;

// Generated 3-lug-2012 10.31.04 by Hibernate Tools 3.4.0.CR1

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Dettagli generated by hbm2java
 */
@Entity
@Table(name = "dettagli", catalog = "cinebot")
public class Dettagli implements java.io.Serializable {

    private static final long serialVersionUID = 1L;
    private String nome;
    private String valore;

    public Dettagli() {
    }

    public Dettagli(String nome) {
        this.nome = nome;
    }

    public Dettagli(String nome, String valore) {
        this.nome = nome;
        this.valore = valore;
    }

    @Id
    @Column(name = "nome", unique = true, nullable = false, length = 32)
    public String getNome() {
        return this.nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Column(name = "valore", length = 65535)
    public String getValore() {
        return this.valore;
    }

    public void setValore(String valore) {
        this.valore = valore;
    }

}

I can not understand why is not enought the @Transactional annotation to auto-open the transaction. What i missed?

Thanks

Tobia
  • 9,165
  • 28
  • 114
  • 219
  • Look like you are using transactional annotation in DAO class. Can you show the spring bean definition/annotation for you dao and also how you are scanning packages? – Sunil Chavan Jul 03 '12 at 13:18
  • I'm using a single Dao class, the @Transactional method is part of that Dao. I think the transaction is not well configured... but i can not find where. – Tobia Jul 03 '12 at 13:29
  • Usually Transactional need to be annotated in the service class. Do you use service class? [Best practices](http://stackoverflow.com/questions/1079114/spring-transactional-annotation-best-practice) – Sunil Chavan Jul 03 '12 at 13:32
  • Actually i'm not using it, i directly call it from Controller, do you think this is the error? – Tobia Jul 03 '12 at 13:45
  • How you are calling this method? creating new object or call on the injected object? – Sunil Chavan Jul 03 '12 at 13:46
  • I had to call it by injected. Seems that Transaction works only it is set, the class is get by injection and the method is public and not selfcalled. – Tobia Jul 04 '12 at 07:15

2 Answers2

1

Just having had a look at this code, it's clearly not going to work with Spring transactional annotations.

You're using a static method and getting your SessionFactory from a static holder.

You need to obtain an instance of your DAO from Spring which is wired with the Spring instance of the SessionFactory. This will allow Spring to proxy the DAO and provide the transactional behaviour.

Alex Barnes
  • 7,174
  • 1
  • 30
  • 50
  • Removed the prop but transaction is still not automatically opened. – Tobia Jul 03 '12 at 13:49
  • Yes: org.hibernate.HibernateException: get is not valid without active transaction at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:348) – Tobia Jul 03 '12 at 13:51
  • I was using HibernateUtil.getSessionFactory().getCurrentSession(); instead of autowiring the sessionfactory.... sorry – Tobia Jul 03 '12 at 14:19
  • No probs. Took me a while to realise what was wrong with the method! – Alex Barnes Jul 03 '12 at 18:47
1

Based on the comments You can recheck below points(though I would not recommend using same)

  • You need to inject/autowire spring DAO into your controller. Annotate the DAO with @Repository
  • Make sure your spring scans and create bean for your DAO class which is done by context:component-scan. Here your dao class should be inside the given package/subpackage.

I would recommend to use service layer between your Controller and DAO. Annotate the service method as @transactional which calls method in DAO. Remember you should not create new instance of any bean in order to call methods in it but inject/autowire Service->Controller and DAO->Service.

Sunil Chavan
  • 2,934
  • 4
  • 25
  • 24