Jack
Jack

Reputation: 6650

Should I use beginTransaction while using @Transactional?

I am quite confused with Spring and Hibernate transactions. I have the following sample code.

I am wondering if

  1. This is a correct way of retrieval or not.
  2. Should I use getCurrentSession().beginTransaction() as well, should I use it in conjunction with @Transactional at all?

Configuration

 <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:2000/HiberProject" />
        <property name="username" value="jack" />
        <property name="password" value="jack" />
    </bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
    depends-on="dataSource">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.hiberproject.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.use_sql_comments">true</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

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

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

Service

@Service
public class SampleRecordsServiceImpl implements SampleRecordsService{

 @Autowired
 SampleRecordsRepository sampleRecordsRepository;

 @Override
 @Transactional(readOnly=true)
 public Record retrieveRecord(long id){
      return sampleRecordsRepository.retrieveRecord(id);
 }
}

Repository

@Repository
public class SampleRecordsRepository implements SampleRecordsRepository{

 @Autowired
 SessionFactory sessioFactory;

 @Override
 public Record retrieveRecord(long id){
     return (Record) sessionFactory.getCurrentSession().get(Record.class,id);
 }
}

Upvotes: 7

Views: 3060

Answers (2)

Sai prateek
Sai prateek

Reputation: 11926

The @Transactional annotation itself defines the scope of a single database transaction. The database transaction happens inside the scope of a persistence context.

The persistence context is just a synchronizer object that tracks the state of a limited set of Java objects and makes sure that changes on those objects are eventually persisted back into the database.

For @Transactional annotation you can set propagation attribute, using Propagation you can handle your tarnsaction in different way like Propagation.REQUIRES_NEW(if you need new transaction on every request) . the default propagation is REQUIRED.

session.beginTransaction() will also either begin a new Transaction if one isn't present, or it will use an existing transaction to begin the unit of work specified.

So you should use either one of approach to manage the transaction.

Upvotes: 4

Sazzadur Rahaman
Sazzadur Rahaman

Reputation: 7126

  1. Yes that's Okay to use only @Transactional annotation like this when you use Spring to manage your transaction.

  2. No. You don't need to do that! If you use @Transactional annotation in your service, then Spring takes care of your persistence layer to manage transaction. All you need is to declare persistence layer specific transaction manager in your Spring configuration. So you do not need to manage transaction with hibernate sessions by using session.beginTransaction() together with @Transactional.

For more information please see the documentation of using @Transactional.

Upvotes: 2

Related Questions