com.googlecode.objectify.impl.TransactorNo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of objectify Show documentation
Show all versions of objectify Show documentation
The simplest convenient interface to the Google App Engine datastore
package com.googlecode.objectify.impl;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.TxnType;
import com.googlecode.objectify.Work;
import java.util.ConcurrentModificationException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Transactor which represents the absence of a transaction.
*
* @author Jeff Schnitzer
*/
/**
* @author jeff
*
* @param
*/
public class TransactorNo extends Transactor
{
/** */
private static final Logger log = Logger.getLogger(TransactorNo.class.getName());
/**
*/
public TransactorNo(Objectify ofy) {
super(ofy);
}
/**
*/
public TransactorNo(Objectify ofy, Session session) {
super(ofy, session);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.Objectify#getTxn()
*/
@Override
public TransactionImpl getTransaction() {
// This version doesn't have a transaction, always null.
return null;
}
/* (non-Javadoc)
* @see com.googlecode.objectify.impl.cmd.Transactor#transactionless()
*/
@Override
public ObjectifyImpl transactionless(ObjectifyImpl parent) {
return parent;
}
/* (non-Javadoc)
* @see com.googlecode.objectify.impl.cmd.Transactor#execute(com.googlecode.objectify.TxnType, com.googlecode.objectify.Work)
*/
@Override
public R execute(ObjectifyImpl parent, TxnType txnType, Work work) {
switch (txnType) {
case MANDATORY:
throw new IllegalStateException("MANDATORY transaction but no transaction present");
case NOT_SUPPORTED:
case NEVER:
case SUPPORTS:
return work.run();
case REQUIRED:
case REQUIRES_NEW:
return transact(parent, work);
default:
throw new IllegalStateException("Impossible, some unknown txn type");
}
}
/* (non-Javadoc)
* @see com.googlecode.objectify.impl.Transactor#transact(com.googlecode.objectify.impl.ObjectifyImpl, com.googlecode.objectify.Work)
*/
@Override
public R transact(ObjectifyImpl parent, Work work) {
return this.transactNew(parent, Integer.MAX_VALUE, work);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.impl.Transactor#transactNew(com.googlecode.objectify.impl.ObjectifyImpl, int, com.googlecode.objectify.Work)
*/
@Override
public R transactNew(ObjectifyImpl parent, int limitTries, Work work) {
while (true) {
try {
return transactOnce(parent, work);
} catch (ConcurrentModificationException ex) {
if (limitTries-- > 0) {
if (log.isLoggable(Level.WARNING))
log.warning("Optimistic concurrency failure for " + work + " (retrying): " + ex);
if (log.isLoggable(Level.FINEST))
log.log(Level.FINEST, "Details of optimistic concurrency failure", ex);
} else {
throw ex;
}
}
}
}
/**
* One attempt at executing a transaction
*/
private R transactOnce(ObjectifyImpl parent, Work work) {
ObjectifyImpl txnOfy = startTransaction(parent);
ObjectifyService.push(txnOfy);
try {
R result = work.run();
txnOfy.flush();
txnOfy.getTransaction().commit();
return result;
}
finally
{
if (txnOfy.getTransaction().isActive()) {
try {
txnOfy.getTransaction().rollback();
} catch (RuntimeException ex) {
log.log(Level.SEVERE, "Rollback failed, suppressing error", ex);
}
}
ObjectifyService.pop();
}
}
/**
* Create a new transactional session by cloning this instance and resetting the transactor component.
*/
ObjectifyImpl startTransaction(ObjectifyImpl parent) {
ObjectifyImpl cloned = parent.clone();
cloned.transactor = new TransactorYes<>(cloned, this);
return cloned;
}
}