@Transactional annotation in Spring

I wrote the code below to implement spring transaction management using @transactional annotation. I still feel like some changes are needed in my DAO layer. May I know what changes are needed. thanks in advance

    @Controller
    public class RestController {


    @Autowired
    DataServices dataServices;

    @RequestMapping(value = "/v1/dist_list/{emailId}/members", method = RequestMethod.GET)
        public @ResponseBody String getDistributionListMember(@PathVariable String emailId) throws Exception, SpringException {



            String retStatus = null;


            retStatus = dataServices.getDistributionListMember(emailId, callerId);

         ]
    }      

    }

      

DataServices.java

    package com.uniteid.services;

    import com.uniteid.model.AIWSuser;

    public interface DataServices {


        public String getDistributionListMember(final String emailId, final String callerID) throws Exception;



    }

      

Below is my service layer where I added the trasactional attribute

    package com.uniteid.services;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import com.uniteid.dao.DataDao;
    import com.uniteid.model.AIWSuser;

    @Service("dataService")
    public class DataServicesImpl implements DataServices {

        @Autowired
        DataDao dataDao;


        @Transactional
        public String getDistributionListMember(String emailId, String callerID)
                throws Exception {
            return dataDao.getDistributionListMember(emailId, callerID);
        }



    }

      

Below is my spring-config file

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
      http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
        xmlns:tx="http://www.springframework.org/schema/tx">

        <context:component-scan base-package="com.uniteid.controller" />
        <mvc:annotation-driven
            content-negotiation-manager="contentNegociationManager" />

        <bean
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:uniteidrest.properties" />
            <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        </bean>

        <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />

            <property name="url">
                <value>${eidms.url}</value>
            </property>
            <property name="username">
                <value>${eidms.username}</value>
            </property>
            <property name="password">
                <value>${eidms.password}</value>
            </property>
        </bean>

        <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
            <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" 
            /> <property name="url" value="jdbc:oracle:thin:@nyvm0467.ptc.un.org:1521:EIDMSUAT" 
            /> <property name="username" value="DBO_EIDMSUAT" /> <property name="password" 
            value="NewPassDBO_EIDMSUAT" /> </bean> -->

        <bean id="contentNegociationManager"
            class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
            <property name="defaultContentType" value="application/json" />
            <property name="ignoreAcceptHeader" value="true" />
        </bean>

        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="annotatedClasses">
                <list>
                    <value>com.uniteid.model.User</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                    <prop key="hibernate.connection.pool_size">10</prop>
                </props>
            </property>
        </bean>

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

        <bean id="persistenceExceptionTranslationPostProcessor"
            class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

        <bean id="dataDao" class="com.uniteid.dao.DataDaoImpl"></bean>
        <bean id="dataServices" class="com.uniteid.services.DataServicesImpl"></bean>
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>

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

      

I still feel like I haven't implemented transaction management properly in the code below. May I know what part of the code can be removed for me to implement it?

    package com.uniteid.dao;


    import java.sql.CallableStatement;

    import java.sql.Connection;

    import java.sql.SQLException;

    import java.sql.Types;

    import java.text.ParseException;

    import java.text.SimpleDateFormat;

    import org.apache.log4j.Logger;

    import org.hibernate.Session;

    import org.hibernate.SessionFactory;

    import org.hibernate.Transaction;

    import org.hibernate.jdbc.Work;

    import org.springframework.beans.factory.annotation.Autowired;


    import com.uniteid.controller.RestController;

    import com.uniteid.model.AIWSuser;

    import com.uniteid.model.User;


    public class DataDaoImpl implements DataDao 
    {



    @Autowired
        \
    SessionFactory sessionFactory;


    Session session = null;

    Transaction tx = null;


    static final Logger logger = Logger.getLogger(DataDaoImpl.class);





    public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
            session = sessionFactory.openSession();
            tx = session.beginTransaction();

            final String[] returnVal2 = { "" };

            session.doWork(new Work() {
                public void execute(Connection connection) throws SQLException {
                    CallableStatement stmt = null;
                    String returnVal = "";

                    stmt = connection.prepareCall("{?=call WS_Distributionlistmember(?,?)}");
                    stmt.registerOutParameter(1, Types.VARCHAR);
                    stmt.setString(2, emailId);
                    stmt.setString(3, callerID);
                    stmt.execute();
                    returnVal = stmt.getString(1);
                    logger.info("RETURN VALUE in getDistributionListMember method :::::: " + returnVal);
                    returnVal2[0] = returnVal;

                    logger.info("Return Value " + returnVal);
                    stmt.close();
                }
            });

            tx.commit();
            session.close();
            return returnVal2[0];
        }


    }

      

+3


source to share


2 answers


Your code:

public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
        session = sessionFactory.openSession();//This is bad
        tx = session.beginTransaction();//This is bad
        tx.commit();//This is bad
        session.close();//This is bad

      

It should be correct:



public String getDistributionListMember(final String emailId, final String callerID) throws Exception {
        session = sessionFactory.getCurrentSession();//good way

      

This is because you said spring to autwired sessionFactory

and now spring does not manage your hibernate session with you. So, that getCurrentSession()

's the right way.

@M. Deinum Thanks for pointing this out.

+1


source


Remove the bean declaration for the bean id transactionManager

and set txManager

instead transactionManager

to the value of the transaction manager. Since you are using hibernate with spring, DatabaseTransactionManager

should instead be used HibernateTransactionManager

to define the transaction boundary. DatabaseTransactionManager

used when interacting directly with the data source without using any ORM or JPA frameworks.

In your service class, define a transaction boundary for the method as shown below, annotation



@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)

      

0


source







All Articles