All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.datastore.Transaction Maven / Gradle / Ivy

There is a newer version: 2.24.2
Show newest version
/*
 * Copyright 2015 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.cloud.datastore;

import com.google.api.core.BetaApi;
import com.google.cloud.datastore.models.ExplainOptions;
import com.google.protobuf.ByteString;
import java.util.Iterator;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;

/**
 * A Google cloud datastore transaction. Similar to {@link Batch} any write operation that is
 * applied on a transaction will only be sent to the Datastore upon {@link #commit}. A call to
 * {@link #rollback} will invalidate the transaction and discard the changes. Any read operation
 * that is done by a transaction will be part of it and therefore a {@code commit} is guaranteed to
 * fail if an entity was modified outside the transaction after it was read. Write operation on this
 * transaction will not be reflected by read operation (as the changes are only sent to the
 * Datastore upon {@code commit}. A usage example:
 *
 * 
{@code
 * Transaction transaction = datastore.newTransaction();
 * try {
 *   Entity entity = transaction.get(key);
 *   if (!entity.contains("last_name") || entity.isNull("last_name")) {
 *     String[] name = entity.getString("name").split(" ");
 *     entity = Entity.newBuilder(entity)
 *         .remove("name")
 *         .set("first_name", name[0])
 *         .set("last_name", name[1])
 *         .build();
 *     transaction.update(entity);
 *     transaction.commit();
 *   }
 * } finally {
 *   if (transaction.isActive()) {
 *     transaction.rollback();
 *   }
 * }
 * }
* * @see Google Cloud * Datastore transactions *

WARNING: This class maintains an internal state in terms of {@link * java.util.LinkedHashMap} and {@link java.util.LinkedHashSet} which gets updated on every * method call performing CRUD operations to record the mutations. Since {@link * java.util.LinkedHashMap} is not thread safe as per its documentation, * This class too should not be treated as a thread safe class. */ @NotThreadSafe public interface Transaction extends DatastoreBatchWriter, DatastoreReaderWriter { interface Response { /** Returns a list of keys generated by a transaction. */ List getGeneratedKeys(); } /** * {@inheritDoc} The requested entity will be part of this Datastore transaction (so a commit is * guaranteed to fail if entity was changed by others after it was seen by this transaction) but * any write changes in this transaction will not be reflected by the returned entity. * *

Example of getting an entity for a given key. * *

{@code
   * String keyName = "my_key_name";
   * Key key = datastore.newKeyFactory().setKind("MyKind").newKey(keyName);
   * Entity entity = transaction.get(key);
   * transaction.commit();
   * // Do something with the entity
   * }
* * @throws DatastoreException upon failure or if no longer active */ @Override Entity get(Key key); /** * {@inheritDoc} The requested entities will be part of this Datastore transaction (so a commit is * guaranteed to fail if any of the entities was changed by others after they were seen by this * transaction) but any write changes in this transaction will not be reflected by the returned * entities. * *

Example of getting entities for several keys. * *

{@code
   * String firstKeyName = "my_first_key_name";
   * String secondKeyName = "my_second_key_name";
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
   * Key firstKey = keyFactory.newKey(firstKeyName);
   * Key secondKey = keyFactory.newKey(secondKeyName);
   * Iterator entitiesIterator = transaction.get(firstKey, secondKey);
   * List entities = Lists.newArrayList();
   * while (entitiesIterator.hasNext()) {
   *   Entity entity = entitiesIterator.next();
   *   // do something with the entity
   *   entities.add(entity);
   * }
   * transaction.commit();
   * }
* * @throws DatastoreException upon failure or if no longer active */ @Override Iterator get(Key... key); /** * {@inheritDoc} The requested entities will be part of this Datastore transaction (so a commit is * guaranteed to fail if any of the entities was changed by others after they were seen by this * transaction) but any write changes in this transaction will not be reflected by the returned * entities. * *

Example of fetching a list of entities for several keys. * *

{@code
   * String firstKeyName = "my_first_key_name";
   * String secondKeyName = "my_second_key_name";
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
   * Key firstKey = keyFactory.newKey(firstKeyName);
   * Key secondKey = keyFactory.newKey(secondKeyName);
   * List entities = transaction.fetch(firstKey, secondKey);
   * for (Entity entity : entities) {
   *   // do something with the entity
   * }
   * transaction.commit();
   * }
* * @throws DatastoreException upon failure or if no longer active */ @Override List fetch(Key... keys); /** * {@inheritDoc} The entities returned by the result of this query will be part of this Datastore * transaction (so a commit is guaranteed to fail if any of the entities was changed by others * after the query was performed) but any write changes in this transaction will not be reflected * by the result. * *

Example of running a query to find all entities with an ancestor. * *

{@code
   * String parentKeyName = "my_parent_key_name";
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("ParentKind");
   * Key parentKey = keyFactory.newKey(parentKeyName);
   * // Build a query
   * Query query = Query.newEntityQueryBuilder()
   *     .setKind("MyKind")
   *     .setFilter(PropertyFilter.hasAncestor(parentKey))
   *     .build();
   * QueryResults results = transaction.run(query);
   * List entities = Lists.newArrayList();
   * while (results.hasNext()) {
   *   Entity result = results.next();
   *   // do something with result
   *   entities.add(result);
   * }
   * transaction.commit();
   * }
* * @throws DatastoreException upon failure or if no longer active */ @Override QueryResults run(Query query); @BetaApi default QueryResults run(Query query, ExplainOptions explainOptions) { throw new UnsupportedOperationException("Not implemented."); } /** * Datastore add operation. This method will also allocate id for any entity with an incomplete * key. As opposed to {@link #add(FullEntity)} and {@link #add(FullEntity...)}, this method will * defer any necessary id allocation to commit time. * *

Example of adding multiple entities with deferred id allocation. * *

{@code
   * IncompleteKey key1 = datastore.newKeyFactory().setKind("MyKind").newKey();
   * FullEntity.Builder entityBuilder1 = FullEntity.newBuilder(key1);
   * entityBuilder1.set("propertyName", "value1");
   * FullEntity entity1 = entityBuilder1.build();
   *
   * IncompleteKey key2 = datastore.newKeyFactory().setKind("MyKind").newKey();
   * FullEntity.Builder entityBuilder2 = FullEntity.newBuilder(key2);
   * entityBuilder2.set("propertyName", "value2");
   * FullEntity entity2 = entityBuilder2.build();
   *
   * transaction.addWithDeferredIdAllocation(entity1, entity2);
   * Response response = transaction.commit();
   * }
* * @throws DatastoreException if a given entity with a complete key was already added to this * transaction or if the transaction is no longer active */ void addWithDeferredIdAllocation(FullEntity... entities); /** * {@inheritDoc} * *

Example of adding a single entity. * *

{@code
   * String keyName = "my_key_name";
   * Key key = datastore.newKeyFactory().setKind("MyKind").newKey(keyName);
   * Entity.Builder entityBuilder = Entity.newBuilder(key);
   * entityBuilder.set("propertyName", "value");
   * Entity entity = entityBuilder.build();
   * transaction.add(entity);
   * transaction.commit();
   * }
* * @throws DatastoreException if a given entity with the same complete key was already added to * this writer, if the transaction is no longer active or if id allocation for an entity with * an incomplete key failed */ @Override Entity add(FullEntity entity); /** * {@inheritDoc} * *

Example of adding multiple entities. * *

{@code
   * String keyName1 = "my_key_name1";
   * String keyName2 = "my_key_name2";
   * Key key1 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName1);
   * Entity.Builder entityBuilder1 = Entity.newBuilder(key1);
   * entityBuilder1.set("propertyName", "value1");
   * Entity entity1 = entityBuilder1.build();
   *
   * Key key2 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName2);
   * Entity.Builder entityBuilder2 = Entity.newBuilder(key2);
   * entityBuilder2.set("propertyName", "value2");
   * Entity entity2 = entityBuilder2.build();
   *
   * transaction.add(entity1, entity2);
   * transaction.commit();
   * }
* * @throws DatastoreException if a given entity with the same complete key was already added to * this writer, if the transaction is no longer active or if id allocation for an entity with * an incomplete key failed */ @Override List add(FullEntity... entities); /** * {@inheritDoc} This operation will be converted to {@link #put} operation for entities that were * already added or put in this writer. * *

Example of updating multiple entities. * *

{@code
   * String keyName1 = "my_key_name1";
   * String keyName2 = "my_key_name2";
   * Key key1 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName1);
   * Entity.Builder entityBuilder1 = Entity.newBuilder(key1);
   * entityBuilder1.set("propertyName", "value3");
   * Entity entity1 = entityBuilder1.build();
   *
   * Key key2 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName2);
   * Entity.Builder entityBuilder2 = Entity.newBuilder(key2);
   * entityBuilder2.set("propertyName", "value4");
   * Entity entity2 = entityBuilder2.build();
   *
   * transaction.update(entity1, entity2);
   * transaction.commit();
   * }
* * @throws DatastoreException if an entity is marked for deletion in this transaction or if the * transaction is no longer active */ @Override void update(Entity... entities); /** * {@inheritDoc} This operation will also remove from this transaction any prior writes for * entities with the same keys. * *

Example of deleting multiple entities. * *

{@code
   * String keyName1 = "my_key_name1";
   * String keyName2 = "my_key_name2";
   * Key key1 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName1);
   * Key key2 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName2);
   * transaction.delete(key1, key2);
   * transaction.commit();
   * }
* * @throws DatastoreException upon failure or if no longer active */ @Override void delete(Key... keys); /** * Datastore put operation. This method will also allocate id for any entity with an incomplete * key. As opposed to {@link #put(FullEntity)} and {@link #put(FullEntity...)}, this method will * defer any necessary id allocation to commit time. * *

Example of putting multiple entities with deferred id allocation. * *

{@code
   * IncompleteKey key1 = datastore.newKeyFactory().setKind("MyKind").newKey();
   * FullEntity.Builder entityBuilder1 = FullEntity.newBuilder(key1);
   * entityBuilder1.set("propertyName", "value1");
   * FullEntity entity1 = entityBuilder1.build();
   *
   * IncompleteKey key2 = datastore.newKeyFactory().setKind("MyKind").newKey();
   * FullEntity.Builder entityBuilder2 = FullEntity.newBuilder(key2);
   * entityBuilder2.set("propertyName", "value2");
   * FullEntity entity2 = entityBuilder2.build();
   *
   * transaction.putWithDeferredIdAllocation(entity1, entity2);
   * Response response = transaction.commit();
   * }
* * @throws IllegalArgumentException if any of the given entities is missing a key * @throws DatastoreException if no longer active */ void putWithDeferredIdAllocation(FullEntity... entities); /** * {@inheritDoc} This operation will also remove from this transaction any prior writes for the * same entity. * *

Example of putting a single entity. * *

{@code
   * String keyName = "my_key_name";
   * Key key = datastore.newKeyFactory().setKind("MyKind").newKey(keyName);
   * Entity.Builder entityBuilder = Entity.newBuilder(key);
   * entityBuilder.set("propertyName", "value");
   * Entity entity = entityBuilder.build();
   * transaction.put(entity);
   * transaction.commit();
   * }
* * @throws DatastoreException if id allocation for an entity with an incomplete key failed or if * the transaction is no longer active */ @Override Entity put(FullEntity entity); /** * {@inheritDoc} This operation will also remove from this transaction any prior writes for the * same entities. * *

Example of putting multiple entities. * *

{@code
   * String keyName1 = "my_key_name1";
   * String keyName2 = "my_key_name2";
   * Key key1 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName1);
   * Entity.Builder entityBuilder1 = Entity.newBuilder(key1);
   * entityBuilder1.set("propertyName", "value1");
   * Entity entity1 = entityBuilder1.build();
   *
   * Key key2 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName2);
   * Entity.Builder entityBuilder2 = Entity.newBuilder(key2);
   * entityBuilder2.set("propertyName", "value2");
   * Entity entity2 = entityBuilder2.build();
   *
   * transaction.put(entity1, entity2);
   * transaction.commit();
   * }
* * @throws DatastoreException if id allocation for an entity with an incomplete key failed or if * the transaction is no longer active */ @Override List put(FullEntity... entities); /** * Commit the transaction. * *

Example of committing a transaction. * *

{@code
   * // create an entity
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
   * Key key = datastore.allocateId(keyFactory.newKey());
   * Entity entity = Entity.newBuilder(key).set("description", "commit()").build();
   *
   * // add the entity and commit
   * try {
   *   transaction.put(entity);
   *   transaction.commit();
   * } catch (DatastoreException ex) {
   *   // handle exception
   * }
   * }
* * @throws DatastoreException if could not commit the transaction or if no longer active */ Response commit(); /** * Rollback the transaction. * *

Example of rolling back a transaction. * *

{@code
   * // create an entity
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
   * Key key = datastore.allocateId(keyFactory.newKey());
   * Entity entity = Entity.newBuilder(key).set("description", "rollback()").build();
   *
   * // add the entity and rollback
   * transaction.put(entity);
   * transaction.rollback();
   * // calling transaction.commit() now would fail
   * }
* * @throws DatastoreException if transaction was already committed */ void rollback(); /** * Returns {@code true} if the transaction is still active (was not committed or rolledback). * *

Example of verifying if a transaction is active. * *

{@code
   * // create an entity
   * KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
   * Key key = datastore.allocateId(keyFactory.newKey());
   * Entity entity = Entity.newBuilder(key).set("description", "active()").build();
   * // calling transaction.active() now would return true
   * try {
   *   // add the entity and commit
   *   transaction.put(entity);
   *   transaction.commit();
   * } finally {
   *   // if committing succeeded
   *   // then transaction.active() will be false
   *   if (transaction.isActive()) {
   *     // otherwise it's true and we need to rollback
   *     transaction.rollback();
   *   }
   * }
   * }
*/ @Override boolean isActive(); /** Returns the transaction associated {@link Datastore}. */ Datastore getDatastore(); ByteString getTransactionId(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy