Announcement Announcement Module
Collapse
No announcement yet.
Grouping multiple SqlUpdates into transactions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Grouping multiple SqlUpdates into transactions

    I have two questions about grouping queries in a transaction:
    1. I have a dao object that has seven private inner classes
    that subclass SqlUpdate - each performs an insert. These seven classes are then called via a public 'add' method.
    I am using PostgreSQL and have my spring applicationContext file defined as follows:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName"><value>org.postgresql.Drive r</value></property>
    <property name="url"><value>jdbcostgresql:dbname</value></property>
    <property name="username"><value>user</value></property>
    <property name="password"><value></value></property>
    </bean>
    <bean id="fooDao" class="FooDaoJdbc">
    <property name="dataSource"><ref local="dataSource"/></property>
    </bean>
    <bean id="fooDaoTx" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="target"><ref bean="fooDao"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="add*">PROPAGATION_REQUIRED,-MyException, -DataAccessException</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
    </property>
    </bean>

    So, statement 1 inserts a top-level object and each additional statement inserts component 'part' objects.
    Based on my reading of the documentation the transaction definition above should ensure that all the
    statements are called transactionally, but they are not - statement 3 may throw an Exception, but statements 1 & 2 are
    not rolled back - i.e. if the addFoo fails on insert of a 'part' object the Foo should not be there either.
    Is there an additional step I am missing?

    2. Is it possible to allow the dao defined above to add a public method call from another method into its transaction
    (i.e. in the 'addFoo' method of FooDao defined above call 'addBar, defined below, and have the whole thing execute in
    one transaction)?
    Something like this:

    <bean id="barDao" class="BarDaoJdbc">
    <property name="dataSource"><ref local="dataSource"/></property>
    </bean>
    <bean id="barDaoTx" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="target"><ref bean="barDao"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="add*">PROPAGATION_MANDATORY, -DataAccessException</prop>
    <prop key="update*">PROPAGATION_MANDATORY</prop>
    <prop key="get*">PROPAGATION_MANDATORY,readOnly</prop>
    </props>
    </property>
    </bean>

    Again, perhaps I have missed something, but I am calling 'addFoo' and a Foo will be inserted into the database, but the
    method may exit with an Exception on 'addBar', but the 'addFoo' inserts are not rolled back.

    Any help is appreciated.

    Regards,

    James

  • #2
    1. Is there an additional step I am missing?
    The configuration seems OK. Which bean are you using in your client code? You should be using fooDaoTx.
    2. Is it possible to allow the dao defined above to add a public method call from another method into its transaction
    Of course, you can inject barDaoTx into barDao and call addBar normally from addFoo.
    HTH

    Comment


    • #3
      Originally posted by irbouho
      ...you can inject barDaoTx into barDao and call addBar normally from addFoo.
      Can you suggest how to do this?

      Comment


      • #4
        1. add a property barDao to class FooDao:
        Code:
        public class FooDao &#123;
          private BarDao barDao;
          public setBarDao&#40;BarDao barDao&#41; &#123;
            this.barDao = barDao;
          &#125;
        
          public void addFoo&#40;&#41; &#123;
            methodOne&#40;&#41;;
            methodTwo&#40;&#41;;
            bar.addBar&#40;&#41;;
          &#125;
        &#125;
        2: configure the injection of the new property:
        Code:
          ...
          <bean id="barDaoTx" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          ...
          </bean>
        
          <bean id="fooDao" class="FooDao">
            <property name="barDao">
              <ref local="barDaoTx">
            </property>
          </bean>
          ...
        HTH

        Comment


        • #5
          Thanks for all the help!

          I have one more question to close the loop:
          Is the aspect appliet 'automatically' or do I have to do an additional step? For example, can I simply call "context.getBean("fooDao").addFoo(myFoo)" to execute all the inserts transactionally or is there another step?

          Thanks again!

          Comment


          • #6
            As I said before, you should use bean fooDaoTx:
            Code:
            context.getBean&#40;"fooDaoTx"&#41;.addFoo&#40;myFoo&#41;
            Spring will then apply the aspect automatically to both your beans.

            Comment

            Working...
            X