Reputation: 395
I have a GAE app with a JSON REST API. For each entity I have a DAO class with the objectify code, and a service using the DAO. The service is responsible for the business logic related to the entity. Some calls to the API are expected to use logic across the services, i.e. calling methods in several services.
I would like each call to the API to be one transaction, i.e. either all datastore operations succeeds and are persisted, or if an exception occurs all datastore operations fails and none of them are persisted. I can see that if I do two separate ofy().transact(...) and throw an exception in between, then the operation of the first ofy.transact() is persisted, but not the second. If I do one ofy().transact() and inside this do one datastore operation, then throw an exception and do a second datastore operation, none of the operations are persisted. From this I assume that rollback only happens if the exception is thrown inside the ofy().transact().
My question is: If I have a API call which works across services, I need to encapsulated the calls to the services in an ofy().transact in order to ensure rollback if an exception occurs? I would like to have kept all my use of objectify in the DAO classes, so an alternative solution would be great.
Thanks, -Louise
Upvotes: 1
Views: 895
Reputation: 13556
Transactions are a cross-cutting concern - basically a bit of thread local state. When you start a transaction, it follows the thread until the transaction completes (no matter how many times you nest calls to transact()
).
If you don't want Objectify-specific classes referenced across your codebase, just make your own wrapper for transact()
. Transactional unit of work is a broad database concept.
However, keep in mind that transactions in the datastore are somewhat limited and you can't just apply "start a transaction" everywhere the way you typically would with an RDBMS.
Upvotes: 1