Announcement Announcement Module
Collapse
No announcement yet.
Spring JDBC not rolling back Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring JDBC not rolling back

    I have all the annotations correct and even see the output log state Spring is rolling back the transaction; however, the Oracle table is not rolled back.

    Here is the class:


    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:dbConnection-context.xml" })
    @TransactionConfiguration(defaultRollback = true)
    @Transactional
    public class JUnitTestCase {

    @Test
    public void testInsert() {
    jdbcForumDAOImpl.insertRegistration("Tom");
    }

    Here is the log output:


    00:52:15.484 [main] DEBUG o.s.t.c.t.TransactionalTestExecutionListener - No method-level @Rollback override: using default rollback [true] for test context [[TestContext@56de56de testClass = JUnitTestCase, testInstance = com.coineta.test.JUnitTestCase@7a2a7a2a, testMethod = testInsert@JUnitTestCase, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6cde6cde testClass = JUnitTestCase, locations = '{classpath:dbConnection-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.Delegati ngSmartContextLoader']]]
    00:52:15.484 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Initiating transaction rollback
    00:52:15.484 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [oracle.jdbc.driver.T4CConnection@53485348]
    00:52:15.484 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Releasing JDBC Connection [oracle.jdbc.driver.T4CConnection@53485348] after transaction
    00:52:15.484 [main] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
    00:52:15.500 [main] INFO o.s.t.c.t.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [[TestContext@56de56de testClass = JUnitTestCase, testInstance = com.coineta.test.JUnitTestCase@7a2a7a2a, testMethod = testInsert@JUnitTestCase, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6cde6cde testClass = JUnitTestCase, locations = '{classpath:dbConnection-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.Delegati ngSmartContextLoader']]]
    00:52:15.500 [main] DEBUG o.s.t.c.t.TransactionalTestExecutionListener - Executing @AfterTransaction method [public void com.coineta.test.JUnitTestCase.afterTransaction()] for test context [[TestContext@56de56de testClass = JUnitTestCase, testInstance = com.coineta.test.JUnitTestCase@7a2a7a2a, testMethod = testInsert@JUnitTestCase, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6cde6cde testClass = JUnitTestCase, locations = '{classpath:dbConnection-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.Delegati ngSmartContextLoader']]]
    00:52:15.500 [main] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:oracle:thin:@192.168.2.113:1521:orcl]
    00:52:15.531 [main] DEBUG o.s.t.c.s.DirtiesContextTestExecutionListener - After test method: context [[TestContext@56de56de testClass = JUnitTestCase, testInstance = com.coineta.test.JUnitTestCase@7a2a7a2a, testMethod = testInsert@JUnitTestCase, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6cde6cde testClass = JUnitTestCase, locations = '{classpath:dbConnection-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.Delegati ngSmartContextLoader']]], class dirties context [false], class mode [null], method dirties context [false].
    00:52:15.531 [main] DEBUG o.s.t.c.s.DirtiesContextTestExecutionListener - After test class: context [[TestContext@56de56de testClass = JUnitTestCase, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6cde6cde testClass = JUnitTestCase, locations = '{classpath:dbConnection-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.Delegati ngSmartContextLoader']]], dirtiesContext [false].
    00:52:15.531 [Thread-4] INFO o.s.c.s.GenericApplicationContext - Closing org.springframework.context.support.GenericApplica tionContext@255e255e: startup date [Mon May 07 00:52:12 EDT 2012]; root of context hierarchy
    00:52:15.531 [Thread-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
    00:52:15.531 [Thread-4] INFO o.s.b.f.s.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultL istableBeanFactory@71b871b8: defining beans [jdbcDataSource,transactionManager,forumDAO,altOrde rDAO,orderDAO,authenticationDAO,org.springframewor k.context.annotation.internalConfigurationAnnotati onProcessor,org.springframework.context.annotation .internalAutowiredAnnotationProcessor,org.springfr amework.context.annotation.internalRequiredAnnotat ionProcessor,org.springframework.context.annotatio n.ConfigurationClassPostProcessor$ImportAwareBeanP ostProcessor#0]; root of factory hierarchy

  • #2
    Please use [ code][/code ] tags when posting code/xml/stacktraces.

    Post the code for your dao and some configuration.

    Comment


    • #3
      Entering DAO and configuration files

      Originally posted by Marten Deinum View Post
      Please use [ code][/code ] tags when posting code/xml/stacktraces.

      Post the code for your dao and some configuration.
      Thanks for responding..

      Configuration file below:
      [code]
      <?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:tx="http://www.springframework.org/schema/tx" xmlns="http://www.springframework.org/schema/p"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

      <bean id="jdbcDataSource"
      class="org.springframework.jdbc.datasource.DriverM anagerDataSource"
      p:driverClassName="oracle.jdbc.xa.client.OracleXAD ataSource" p:url="jdbc:oracle:thin:@192.168.2.113:1521:orcl"
      p:username="xxxxx" password="xxxxx />


      <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSou rceTransactionManager">
      <property name="dataSource" ref="jdbcDataSource" />
      </bean>

      <bean id="forumDAO" class="com.web.test.JDBCForumDAOImpl">
      <property name="dataSource" ref="jdbcDataSource" />
      </bean>
      </beans>
      [/code ]

      DAO code below:
      Code:
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.Statement;
      
      import javax.sql.DataSource;
      
      public class JDBCForumDAOImpl {
      
      	private DataSource dataSource;
      
      	public void setDataSource(DataSource dataSource) {
      		this.dataSource = dataSource;
      	}
      
      
      	public String insertRegistration(String userName) {
      		Connection connection = null;
      		Statement statement = null;
      		ResultSet resultSet = null;
      		try {
      			/**
      			 * Open the connection
      			 */
      			connection = dataSource.getConnection();
      			/**
      			 * Prepare the statement
      			 */
      			statement = connection.createStatement();
      
      			String sql = "INSERT INTO Registration " + "VALUES ('" + userName +"')";
      			statement.executeUpdate(sql);
      
      
      		} catch (SQLException e) {
      			/**
      			 * Handle any exception
      			 */
      			e.printStackTrace();
      		} finally {
      			try {
      				/**
      				 * Close the resultSet
      				 */
      				if (resultSet != null) {
      					resultSet.close();
      				}
      				/**
      				 * Close the connection
      				 */
      				if (connection != null) {
      					connection.close();
      				}
      			} catch (SQLException e) {
      				/**
      				 * Handle any exception
      				 */
      				e.printStackTrace();
      			}
      		}
      		return null;
      	}
      
      
      }

      Comment


      • #4
        And the rollback should happen why?! You are doing your own connection management and executing queries directly without using spring or tapping into spring.

        Use the JdbcTemplate instead of the datasource directly saves you a lot of ugly code. Also you code is flawed (security wise) NEVER NEVER NEVER use string concat to create a query with parameters. Use placeholders (?) for that. Your current code makes it possible to do sql injection...

        Comment


        • #5
          Thanks for responding..

          The example that was posted is a very simple example via Statement. Why start with a difficult example? Once the Spring Framwork is working correctly, I'll make it Judy proof by using prepared statements..

          Executing queries without tapping into Spring? The objective is to test the DAO without change anything, for once the datasource object is set, the DAO does execute the query successfully as is. Does the DAO need to import Spring resources for it to work sucessful? What happens if I want to test Legacy JDBC code without changing anything on the DAO side? Knowing this, I do want to use the jdbcTemplete framework.

          Managing my own connection? Spring is being used(the XML file is being read to retrieve data source connection information) to bind/create the connection since the queries work, correct?

          Please see the link below. I do not believe is uses JdbcTemplete and it's very similar to the code posted:

          http://www.mkyong.com/spring/maven-spring-jdbc-example/

          Comment


          • #6
            Managing my own connection? Spring is being used(the XML file is being read to retrieve data source connection information) to bind/create the connection since the queries work, correct?
            Yes you are managing your own connection.. You are calling getConnection and that ALWAYS gives you a NEW connection because, as I stated, you aren't using spring.

            The objective is to test the DAO without change anything, for once the datasource object is set, the DAO does execute the query successfully as is. Does the DAO need to import Spring resources for it to work sucessful? What happens if I want to test Legacy JDBC code without changing anything on the DAO side?
            If you want to test legacy code you need to wrap your datasource in a TransactionAwareDataSourceProxy as explained in the reference guide. This will wrap the datasource and connections and taps into springs transaction management.

            Please see the link below. I do not believe is uses JdbcTemplete and it's very similar to the code posted:
            The code is similair BUT is still doesn't use spring to manage transactions and resources and the latter is the problem. You want to use spring to manage your transactions but next don't take an effort to make this possible (by either using JdbcTemplate or using the TransactionAwareDataSourceProxy).

            The example that was posted is a very simple example via Statement. Why start with a difficult example? Once the Spring Framwork is working correctly, I'll make it Judy proof by using prepared statements..
            I understand it is a sample the problem with this kind of code is that it never gets changed because "it simply works" and as such remains in production with all security risks at hand. You don't want to know how many demo or proof-of-concept applications are in production because 'well it works isn't it'....

            Comment


            • #7
              Thanks for responding Marten...

              ok..I reviewed javadoc and it looks as though the only change is to the configuration file; it needs to include a delcaration for TransactionAwareDataSourceProxy to wrap the current datasource conection. It does this by referencing the existing datasource declaration id(datasource). The DAO should not have to change since the dataSource connection within the DAO will be wrapped by TransactionAwareDataSourceProxy. Now Spring should be controlling the transaction and a Rollback should be possible?

              Code:
              <bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
                   <constructor-arg ref="dataSource"/>
              </bean>
              
              <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
                     p:driverClassName="oracle.jdbc.xa.client.OracleXADataSource" p:url="jdbc:oracle:thin:@192.168.2.113:1521:orcl"
                     p:username="xxxxx" p:password="xxxxx />

              Comment

              Working...
              X