Удалить объект BATCH не имеет никакого эффекта - PullRequest
1 голос
/ 29 февраля 2012

У меня есть DAO ниже, с транзакционным удалением для объекта и в пакете .Удаление одного объекта за раз работает просто отлично.

Пакетное удаление НЕ имеет никакого эффекта: приведенный ниже код является простым и понятным IMO, но вызов deleteMyObjects (Long [] ids) - который вызывает delete (Iterable keysOrEntities) из Objectify - не имеет никакого эффекта!

public class MyObjectDao {

    private ObjectifyOpts transactional = new ObjectifyOpts().setBeginTransaction(true);

    private ObjectifyOpts nonTransactional = new ObjectifyOpts().setBeginTransaction(false);

    private String namespace = null;

    public MyObjectDao(String namespace) {
        Preconditions.checkNotNull(namespace, "Namespace cannot be NULL");
        this.namespace = namespace;
    }

    /**
     * set namespace and get a non-transactional instance of Objectify
     * 
     * @return
     */
    protected Objectify nontxn() {
        NamespaceManager.set(namespace);
        return ObjectifyService.factory().begin(nonTransactional);
    }

    /**
     * set namespace and get a transactional instance of Objectify
     * 
     * @return
     */
    protected Objectify txn() {
        NamespaceManager.set(namespace);
        Objectify txn =  ObjectifyService.factory().begin(transactional);
        log.log(Level.FINE, "transaction <" + txn.getTxn().getId() + "> started");
        return txn;
    }

    protected void commit(Objectify txn) {
        if (txn != null && txn.getTxn().isActive()) {
            txn.getTxn().commit();
            log.log(Level.FINE, "transaction <" + txn.getTxn().getId() + "> committed");
        } else {
            log.log(Level.WARNING, "commit NULL transaction");
        }
    }

    protected void rollbackIfNeeded(Objectify txn) {
        if (txn != null && txn.getTxn() != null && txn.getTxn().isActive()) {
            log.log(Level.WARNING, "transaction <" + txn.getTxn().getId() + "> rolling back");
            txn.getTxn().rollback();
        } else if (txn == null || txn.getTxn() == null) {
            log.log(Level.WARNING, "finalizing NULL transaction, not rolling back");
        } else if (!txn.getTxn().isActive()) {
            log.log(Level.FINEST, "transaction <" + txn.getTxn().getId() + "> NOT rolling back");
        }
    }


    public void deleteMyObject(Long id) {
        Objectify txn = null;
        try {
            txn = txn();
            txn.delete(new Key<MyObject>(MyObject.class, id));
            commit(txn);
        } finally {
            rollbackIfNeeded(txn);
        }
    }

    public void deleteMyObjects(Long[] ids) {
        Objectify txn = null;
        List<Key<? extends MyObject>> keys = new ArrayList<Key<? extends MyObject>>();
        for (long id : ids) {
            keys.add(new Key<MyObject>(MyObject.class, id));
        }
        try {
            txn = txn();
            txn.delete(keys);
            commit(txn);
        } finally {
            rollbackIfNeeded(txn);
        }
    }
}

Когда я вызываю deleteMyObjects (Long []), я не вижу ничего подозрительного в журналах ниже.Транзакция совершается просто отлично, без ошибок.Но данные не влияют.Перебирая один и тот же список идентификаторов и удаляя объекты по одному, работает просто отлично.

Feb 29, 2012 8:37:42 AM com.test.MyObjectDao txn
FINE: transaction <6> started
Feb 29, 2012 8:37:42 AM com.test.MyObjectDao commit
FINE: transaction <6> committed
Feb 29, 2012 8:37:42 AM com.test.MyObjectDao rollbackIfNeeded
FINEST: transaction <6> NOT rolling back

Но данные остаются неизменными и присутствуют в хранилище данных!?!?!

Любая помощь приветствуется.

ОБНОВЛЕНИЕ

Заходя в код Objectify, мне интересно, имеет ли это какое-то отношение к пространству имен?Прямо здесь, в коде объекта:

@Override
public Result<Void> delete(Iterable<?> keysOrEntities)
{
    // We have to be careful here, objs could contain raw Keys or Keys or entity objects or both!
    List<com.google.appengine.api.datastore.Key> keys = new ArrayList<com.google.appengine.api.datastore.Key>();

    for (Object obj: keysOrEntities)
        keys.add(this.factory.getRawKey(obj));

    return new ResultAdapter<Void>(this.ads.delete(this.txn, keys));
}

Когда я проверяю this.factory.getRawKey (obj) в отладке, я замечаю, что пространство имен ключа пусто. NamespaceManager.get () однако возвращает правильное пространство имен!?

enter image description here

1 Ответ

3 голосов
/ 29 февраля 2012

Пространство имен не было задано при создании ключей.

Пространство имен должно быть установлено ПЕРЕД созданием ключа!

Таким образом, переписав его так, я решил эту проблему:

public void deleteMyObjects(Long[] ids) {
    Objectify txn = null;
    try {
        txn = txn();
        List<Key<MyObject>> keys = new ArrayList<Key<MyObject>>();
        for (long id : ids) {
            keys.add(new Key<MyObject>(MyObject.class, id));
        }
        txn.delete(keys);
        commit(txn);
    } finally {
        rollbackIfNeeded(txn);
    }
}

Затем я вызываю это:

new MyObjectDAO("somenamespace").delete({ 1L, 34L, 116L });
...