Why not put the rollback code in the destructor of your database abstraction layer? You're already keeping a stack of open transactions: if the destructor is called (the object is going out of scope) and there're any open transactions, the sensible thing is to rollback all those transactions and then throw an exception telling about the fact.
That way any exception anywhere (not only exceptions thrown by your database layer) automatically rollback the transactions as required.
That way any exception anywhere (not only exceptions thrown by your database layer) automatically rollback the transactions as required.