Announcement Announcement Module
Collapse
No announcement yet.
Rolling back on exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rolling back on exception

    Hello guys,

    I am just curious. If I have a DAO that has this method:

    PHP Code:
    public class MyDao extends DaoHibernateSupport {

         .....................

         public 
    Object save(Object object) {
             return 
    getHibernateTemplate.merge(object);
             
    // OR .saveOrUpdate(object);
         
    }

         .....................


    and I have a code like this:

    PHP Code:
    public class SomeClass {

         private 
    MyDao myDao;

         .....................

          public 
    void someMethod() {
              
    SomeTable1 table1 = new SomeTable1();
              
    SomeTable2 table2 = new SomeTable2();

              
    // some logic _ 1

              
    myDao.save(table1);


             
    // some logic _ 2


             
    myDao.save(table2);
          }

         .....................


    I would just like to ask if what happens when in the some logic _ 2 part an exception is thrown. Will the save on table1 be rolled back?

    I've asked this question because I consider the someMethod a single ATOMIC transaction. So if I cant do an insert in table1, I should not be able to do an insert on table2, and vice versa..

    Thanks guys for the advise

    -marcKun

  • #2
    I would just like to ask if what happens when in the some logic _ 2 part an exception is thrown. Will the save on table1 be rolled back?
    It depends

    I've asked this question because I consider the someMethod a single ATOMIC transaction.
    You should do the follow, for each DAO create a BO (sometimes called service)
    each BO method (here it should be Transactional) should call each DAO method
    Something like
    Code:
    BO1 (call methodOneBo(...) Transactional to call methodOneDao(...)  in DAO1) 
           DAO1 (use methodOneDao(...) to work with the DB) 
    
    BO2 (call methodTwoBo(...) Transactional to call methodTwoDao(...)  in DAO2) 
           DAO2 (use methodTwoDao(...) to work with the DB)
    Now for your situation you should wrap both BO1-2 inside of other BO I mean
    BO3 -> BO1 and BO2, where BO3 must has a Transactional method wraping each method

    Code:
    BO3 ( use methodThreeBo(...) Transactionl to call: 
          BO1 use methodOneBo(...)  and BO2 use methodTwoBo(...) )
    Like all BOx are Transactional and BO3 Wraps BO1-2 and they are Transactional
    if your DAO2 fails, therefore the Transactional rollback in BO2 works, and like this BO2 is wraped with BO3 (again Transactional) it does that BO1 rollback too all stay in consistent state

    I hope you see my point

    I wrote time ago here
    Help For Transaction Logic For Business Object's

    Now the *It depends* in the beginning of my reply is that inside of DAO for each method you can do transactional too, therefore perhaps (not tested) your logic in your code would work.

    I suggest the first approach

    HTH

    Comment


    • #3
      Hello Sir,

      I think I get what you mean, but Im not sure how to do it. I have setup my hibernate-spring like this:

      hibernate.cfg.xml:

      PHP Code:
      .....
      <
      session-factory>
              <
      property name="connection.username">root</property>
              <
      property name="connection.url">jdbc:mysql://localhost:3306/crown</property>
              
      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
              <
      property name="myeclipse.connection.profile">MySQL</property>
              <
      property name="connection.password"></property>
              <
      property name="connection.driver_class">com.mysql.jdbc.Driver</property>
              <
      property name="connection.autocommit">true</property>
              
              <!-- 
      Connection Pooling configusing cp30 -->
              <
      property name="hibernate.c3p0.max_size">5</property>
              <
      property name="hibernate.c3p0.min_size">1</property>
              <
      property name="hibernate.c3p0.timeout">5000</property>
              <
      property name="hibernate.c3p0.max_statements">0</property>
              <
      property name="hibernate.c3p0.acquire_increment">3</property>
              <
      property name="hibernate.c3p0.idle_test_period">300</property>
              
              <
      mapping class="model.Customers" />
              <
      mapping class="model.AccountInfo" />
              <
      mapping class="model.CreditLogs" />
      ......
          </
      session-factory
      and my applicationContext.xml like this:

      PHP Code:
          <!-- hibernate specific configuration -->
          <
      bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
              <
      property name="configLocation" value="classpath:hibernate.cfg.xml" />
          </
      bean>
          
          <
      bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
              <
      property name="sessionFactory" ref="sessionFactory" />
          </
      bean>

      <
      bean id="daoInterface" class="dao.implementations.SampleDaoImpl">
          <
      property name="sessionFactory" ref="sessionFactory" />
      </
      bean>
      <
      bean id="serviceInterface" class="service.implementations.SampleServiceImpl">
           <
      property name="daoInterface" ref="daoInterface" />
      </
      bean
      and my action class (or controller) will call service.save(object). service is instance of serviceInterface and save is a method of serviceInterface. Here is my sample code on SampleServiceImpl which implements serviceInterface.

      PHP Code:
      public class SampleServiceImpl implements ServiceInterface {
           private 
      DaoInterface daoInterface;

           
      //setters

           
      public Object save(Object o) {
               
      dao.save(o);
               
      // some logic to create an ActionLog object.
               
      dao.save(actionLog);
           }

      will this set up do? like when some logic to create an ActionLog object throws an exception, the transaction is rolled back? im not sure if my setup is transactional.

      thank you,.

      -marckun

      Comment


      • #4
        Originally posted by marcKun View Post
        ...

        will this set up do? like when some logic to create an ActionLog object throws an exception, the transaction is rolled back? im not sure if my setup is transactional.

        thank you,.

        -marckun
        Your setup is not transactional. Check the reference for more details - 9. Transaction management

        Comment


        • #5
          and my action class (or controller) will call service.save(object). service is instance of serviceInterface and save is a method of serviceInterface. Here is my sample code on SampleServiceImpl which implements serviceInterface.
          seems that you didnt read well my previous post, about how to wrap many services(BO) inside of other service, the wrapper bo service should called by your controller

          like our friend denis told you read first such link

          let us know your advance

          Regards

          Comment


          • #6
            Originally posted by dr_pompeii View Post
            seems that you didnt read well my previous post, about how to wrap many services(BO) inside of other service, the wrapper bo service should called by your controller

            like our friend denis told you read first such link

            let us know your advance

            Regards
            Hmmm I really tried to read and understand your post and read the links you've given me. I know that the bottom line is to make my BO (service) 's method transactional right, so when an exception occured, the entire transaction will be rolled back.

            But I am having a hard time setting my services transactional. Here's what i did.


            PHP Code:
                <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                    <
            property name="configLocation" value="classpath:hibernate.cfg.xml" />
                </
            bean>
                
                <
            bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                    <
            property name="sessionFactory" ref="sessionFactory" />
                </
            bean>
                
                <!-- 
            the transactional advice -->
                <
            tx:advice id="txAdvice" transaction-manager="transactionManager">
                    <
            tx:attributes>
                        <!-- 
            all methods starting with get are read-only -->
                        <
            tx:method name="get*" read-only="true"/>
                        <!-- 
            other methods will get the default transaction settings AND ANY EXCEPTION should trigger a roll back-->
                        <
            tx:method name="*" rollback-for="Exception"/>
                    </
            tx:attributes>
                </
            tx:advice>
                
                <
            aop:config>
                    <
            aop:pointcut id="services" expression="execution(* crown.services.implementations.*.*(..))"/>
                    <
            aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>
                </
            aop:config
            All my services implementations are placed in crown.services.implementations.* packages.

            Now what i did im my code is this:

            PHP Code:
            package crown.services.implementations

            public class SampleImpl {
                private 
            Dao dao;

                public 
            void setDao(Dao dao) {
                   
            this.dao dao;
                }

                public 
            MyModel atomicTransaction(MyModel myModel) {
                    
            dao.save(myModel);
                   
                     if(
            true) {
                         
            // this is for verying if a rollback is done
                         
            throws new Exception("Must rollback");
                     }

                     
            // logs this transaction
                     
            dao.save(new LogModel(myModel));
                     return 
            myModel;
                }

            But when I check the database after running the Test, the record is persisted. What have I lack in my configuration??

            Sorry, I really did try reading and reading before i started this thread but it seems myself is not enough.

            Please advise.

            -marckun
            Last edited by marcKun; Aug 19th, 2009, 04:54 AM.

            Comment


            • #7
              Originally posted by marcKun View Post
              But when I check the database after running the Test, the record is persisted. What have I lack in my configuration??
              What does your test look like, including the configuration?

              - Sam

              Comment


              • #8
                Originally posted by Sam Brannen View Post
                What does your test look like, including the configuration?

                - Sam
                sorry...

                iv just discovered my database table's engine is MyISAM.. i thought it was InnoDB. It's working smoothly now.

                Thank you
                -marckun

                Comment

                Working...
                X