Fabio B.
Fabio B.

Reputation: 9400

@Transactional questions and how to use with @Service

My service makes use of a generic DAO (which explicitly uses Hibernate session factory). I have spent some time before I discovered this error

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

I annotated my service and all works perfectly. Now I want to use context path scanning, and remove this line from my configuration:

<bean id="societaService" class="it.trew.prove.services.SocietaService" />

So.... here's my final version:

@Service
@Transactional(readOnly = true)
public class SocietaService {

    private Dao societaDao;

    @Autowired
    public void setSocietaDao(Dao societaDao) {
        this.societaDao = societaDao;
    }

    public void salvaSocieta(Societa s) {
        societaDao.save(s);
    }

    public List<Societa> listAll() {
        return societaDao.getAll(Societa.class);
    }

    public void deleteById(Long id) {
        societaDao.delete(getSocieta(id));
    }

    public Societa getSocieta(String id) {
        return getSocieta(Long.parseLong(id));
    }

    public Societa getSocieta(Long id) {
        return societaDao.get(Societa.class, id);
    }
}

Adding @Service annotation makes my app give the awful hibernate error above. Why? Removing @Service and configuring the service bean via xml = it works. WHY??

In addition:

EDIT

Here's my context xml:

<context:annotation-config />   
<context:component-scan base-package="it.trew.prove" /> 

<!--  Hibernate -->

<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.google.appengine.api.rdbms.AppEngineDriver" />
<property name="url" value="jdbc:google:rdbms://xxx:xxx/xxx" />
</bean>


<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="annotatedClasses">
        <list>
            <value>it.trew.prove.model.beans.Scadenza</value>
            <value>it.trew.prove.model.beans.Fornitore</value>
            <value>it.trew.prove.model.beans.Societa</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <!-- <prop key="hibernate.hbm2ddl.import_files">/setup.sql</prop> -->
        </props>
    </property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

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

Upvotes: 1

Views: 3974

Answers (2)

Caesar Ralf
Caesar Ralf

Reputation: 2233

First of all, you need to tell spring to enable Transactional annotation with something like that:

<tx:annotation-driven transaction-manager="transactionManager" />

Second, if you use @Transactional at class level, any call to a method of your Service will be transactional. Whether it starts a transaction or not depends on the "propagation" attribute. The default is start one if none started in this session (Propagation.REQUIRED). If you use @Transactional only at class level, all of your methods will inherit its attributes, i.e., if you set "readOnly = true", all of yours methods will be read only, thus, updates/saves/delete won't work. I would recommend you to read more the Spring Transaction Management Doc

Upvotes: 1

blitzqwe
blitzqwe

Reputation: 2040

Did you enabled annotations ?

<context:annotation-config />

and

<context:component-scan base-package="org.example"/>

this will enable annotations like @Service, @Component and @Repository

Upvotes: 3

Related Questions