Announcement Announcement Module
No announcement yet.
Help with read-only transactions? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with read-only transactions?

    I'm sure I must be missing some small something, but I can't get read-only transactions to actually work for me. I hope someone can offer up something that might help. My environment is JDK 1.4.2_13, MySQL 5.0.27, Spring 1.2.8, and Hibernate 3.0.5. Data access is working fine with all service methods defined to reside inside read-write transactions.

    I've been through the old forum posts, but didn't spot anything that I think I've missed.

    Here is a snippet of my context that I'm trying to get to work:

    	<bean id="service:item" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="target">
    			<bean class="com.enttek.cim.service.ItemServiceImpl">
    				<constructor-arg ref="dao:item"/>
    				<constructor-arg ref="service:auditing"/>
    				<constructor-arg ref="service:backOffice"/>
    				<constructor-arg ref="service:period"/>
    				<constructor-arg ref="dao:count"/>
    				<constructor-arg ref="dao:receive"/>
    				<constructor-arg ref="dao:transfer"/>
    				<constructor-arg ref="dao:siteTransferIn"/>
    				<constructor-arg ref="dao:vendor"/>
    		<property name="transactionManager" ref="transactionManager"/>
    		<property name="transactionAttributes">
                   <prop key="get*">PROPAGATION_REQUIRED, readOnly</prop>
                   <prop key="find*">PROPAGATION_REQUIRED, readOnly</prop>
                   <prop key="save*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                   <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                   <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
    		<property name="preInterceptors">
    				<ref local="securityValidationAdvice"/>
    I continue to get read-write transactions for the get* methods with this change in place. Any help? Thoughts?


  • #2
    How are you checking it. Marking a transaction readOnly is only an advice to the underlying jdbc connection to optimize the connection. However it is up to the jdbc connection/provider to do something with it or simply ignore it.


    • #3
      I've got a pretty simple test that I'm using to check the results.

            Item item1 = (Item) itemService.getById(glbItem.getId());
            String name1 = item1.getName();
            String code1 = item1.getCode();
            item1.setCode("Changed Code");
            Item item2 = (Item) itemService.getById(glbItem.getId());
            String name2 = item2.getName();
            String code2 = item2.getCode();
            assertEquals(name1, name2);
            assertEquals(code1, code2);
      The changed code should not be saved, but the getById() call that follows seems to force a flush of the cache making the change permanent. This test fails, by the way because the codes are not equivalent anymore.

      Is there indeed a way to get a transaction to ignore changes to objects in the cache and discard them instead of flushing them into permanency?



      • #4
        Assuming you are using it from within a Spring test case. The transaction boundary is then expanded to the Spring TestCase. A transaction is started before the testmethod is executed. Hence no read-only transaction.

        Also you getById is a readonly transaction, however as soon as you leave the getById method you aren't inside a read-only transaction anymore. Changes made to the objects are indeed persisted. The flushing is there because of the endTransaction method.

        To really test your read-only transaction you should execute the setCode from within the getById method.


        • #5
          I see. I think my test case is probably flawed in that respect, then.

          I do actually have a business case in which a get* method modifies an object, but we do not want those modifications persisted.

          Thanks for the input. I do have a couple of ideas to pursue now.


          • #6
            I would guess you could achieve what you want by either called preventTransaction() in the TestCase or just extend one of the none transactional tests instead.


            • #7
              While I see preventTransaction() clearly in the API JavaDoc, it doesn't appear to be available to my derived test case class. Drilling down into the hierarchy source, it doesen't appear to be in the AbstractTransactionalSpringContextTests class, either.

              Is it possible that it was in an older version 1.2.x and was removed in 1.2.8?

              I did get a co-worker to double-check me, just in case I'm going insane. :-)


              • #8
                Well, I managed to get around the problem, anyway. I just called endTransaction() first thing in my test so that the only transactions were those defined in my service. That was enough to truly expose the root of the problem and I could prove to myself what was going on.

                Thanks for all the input! Much appreciated!