3

May i know how to create childClass if my childClass method getInfoFromDB() and saveToDB() need to do different logic?

public abstract class BaseClass {
    public abstract Object doTransaction();
    public Object executeTrans() {
          //do something
          tx.begin();            
          this.doTransaction();
          tx.commit();

    }
}
public childClass extends BaseClass{
    @Override
    public Object doTransaction(){
        //overide to get something from database so can only be used for getInfoFromDB() and not for saveToDB()
        return something;
    }
    public List<String> getInfoFromDB(){
        super.executeTrans();
    }
    public void saveToDB(){
        super.executeTrans() ;
    }
}
Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
cometta
  • 35,071
  • 77
  • 215
  • 324

3 Answers3

4

You should use the template pattern in this case, something like this:

public abstract class BaseClass 
{      
  public Object executeTrans(Template template) 
  {
    tx.begin();            
    template.doTransaction();
    tx.commit();    
  }
}

public interface Template
{
  public void doTransaction();
}

public childClass extends BaseClass
{
  public List<String> getInfoFromDB()
  {
    executeTrans(
      new Template()
      {
        public void doTransaction() 
        {
          ...do get info from DB here.
        }
      }
    );
  }

  public void saveToDB()
  {
    executeTrans(
      new Template()
      {
        public void doTransaction() 
        {
          ...do save to DB here.
        }
      }
    );
  }
}

Saying that, I'd advise using the Spring JDBC template classes rather than rolling your own - they've been tried and tested and have solved the problems you'll run into with nested transactions etc.

Nick Holt
  • 33,455
  • 4
  • 52
  • 58
  • pls correct me if i'm wrong. by having childClass extends BaseClass; executeTrans () method for saveToDB() and getInfoFromDB() will be calling the same executeTrans () 's tx.begin and tx.close(). will this be ok ? or should it be separate new instant? – cometta Aug 14 '09 at 08:49
  • may i know what is the "Template" type that u put there? – cometta Aug 14 '09 at 08:52
  • is the template class just look like this --> class Template(){ public void doTransaction(){}; } ? – cometta Aug 14 '09 at 09:00
  • Yes, both methods will use the same tx object. Without knowing more about what tx is and the object lifecycles it's hard to say if it's ok, although transaction management is typically related to the database connection you are using so it probably shouldn't be a member variable. Like I said, take a look at how the Spring JDBC templates work - they're pretty straight forward and deal with all these issues. – Nick Holt Aug 14 '09 at 09:01
  • The Template interface is just there to demonstrate the template pattern. I'll add its definition in for clarity. – Nick Holt Aug 14 '09 at 09:02
  • This solution looks like a combination of the template method pattern and the strategy pattern. There seems to be no need to extend BaseClass, rather than simply having a field or local variable of type BaseClass. Is there something in the way Spring is constructed, which forces you to use inheritance here? – Jørgen Fogh Aug 22 '14 at 08:10
1

Pass a Runnable containing the different logic to the executeTrans() method.

However, I'm not sure the template method pattern is really what you need here (and how is it handling rollbacks?). You may want to look into a framework such as Spring that allows declarative transactions.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
1

Nick, the "tx" that i going to use look like below. judging from the code, best practise, is the lifecycle is ok since it's called by both savetodb() and getinfofromdb()

public abstract class BaseClass 
{      
  public Object executeTrans(Template template) 
  {
        // PersistenceManager pm = ...;
        Transaction tx = pm.currentTransaction();
        try {
            tx.begin();
             template.doTransaction();
            tx.commit();
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
        }

  }
}
cometta
  • 35,071
  • 77
  • 215
  • 324
  • I don't know much about JDO (I think that's what you're using) but it looks about right except for the finally block - while this will probably work I'd do the rollback if an exception occurs. – Nick Holt Aug 14 '09 at 09:51