Interface Transaction

  • All Superinterfaces:
    DatastoreBatchWriter, DatastoreReader, DatastoreReaderWriter, DatastoreWriter

    @NotThreadSafe
    public interface Transaction
    extends DatastoreBatchWriter, DatastoreReaderWriter
    A Google cloud datastore transaction. Similar to Batch any write operation that is applied on a transaction will only be sent to the Datastore upon commit(). A call to 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 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 commit. A usage example:
    
     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 Also:
    Google Cloud Datastore transactions

    WARNING: This class maintains an internal state in terms of java.util.LinkedHashMap and java.util.LinkedHashSet which gets updated on every method call performing CRUD operations to record the mutations. Since java.util.LinkedHashMap is not thread safe as per its documentation, This class too should not be treated as a thread safe class.

    • Method Detail

      • get

        Entity get​(Key key)
        Returns an Entity for the given Key or null if it doesn't exist. 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.

        
         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
         
        Specified by:
        get in interface DatastoreReader
        Throws:
        DatastoreException - upon failure or if no longer active
      • get

        Iterator<Entity> get​(Key... key)
        Returns an Entity for each given Key that exists in the Datastore. The order of the result is unspecified. Results are loaded lazily, so it is possible to get a DatastoreException from the returned Iterator's hasNext or next methods. 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.

        
         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<Entity> entitiesIterator = transaction.get(firstKey, secondKey);
         List<Entity> entities = Lists.newArrayList();
         while (entitiesIterator.hasNext()) {
           Entity entity = entitiesIterator.next();
           // do something with the entity
           entities.add(entity);
         }
         transaction.commit();
         
        Specified by:
        get in interface DatastoreReader
        Throws:
        DatastoreException - upon failure or if no longer active
        See Also:
        DatastoreReader.get(Key)
      • fetch

        List<Entity> fetch​(Key... keys)
        Returns a list with a value for each given key (ordered by input). null values are returned for nonexistent keys. When possible prefer using DatastoreReader.get(Key...) to avoid eagerly loading the results. 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.

        
         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<Entity> entities = transaction.fetch(firstKey, secondKey);
         for (Entity entity : entities) {
           // do something with the entity
         }
         transaction.commit();
         
        Specified by:
        fetch in interface DatastoreReader
        Throws:
        DatastoreException - upon failure or if no longer active
      • run

        <T> QueryResults<T> run​(Query<T> query)
        Submits a Query and returns its result. 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.

        
         String parentKeyName = "my_parent_key_name";
         KeyFactory keyFactory = datastore.newKeyFactory().setKind("ParentKind");
         Key parentKey = keyFactory.newKey(parentKeyName);
         // Build a query
         Query<Entity> query = Query.newEntityQueryBuilder()
             .setKind("MyKind")
             .setFilter(PropertyFilter.hasAncestor(parentKey))
             .build();
         QueryResults<Entity> results = transaction.run(query);
         List<Entity> entities = Lists.newArrayList();
         while (results.hasNext()) {
           Entity result = results.next();
           // do something with result
           entities.add(result);
         }
         transaction.commit();
         
        Specified by:
        run in interface DatastoreReader
        Throws:
        DatastoreException - upon failure or if no longer active
      • addWithDeferredIdAllocation

        void addWithDeferredIdAllocation​(FullEntity<?>... entities)
        Datastore add operation. This method will also allocate id for any entity with an incomplete key. As opposed to add(FullEntity) and add(FullEntity...), this method will defer any necessary id allocation to commit time.

        Example of adding multiple entities with deferred id allocation.

        
         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();
         
        Specified by:
        addWithDeferredIdAllocation in interface DatastoreBatchWriter
        Throws:
        DatastoreException - if a given entity with a complete key was already added to this transaction or if the transaction is no longer active
      • add

        Entity add​(FullEntity<?> entity)
        Datastore add operation: inserts the provided entity. This method will automatically allocate an id if necessary. If entity has a complete key and was already marked for deletion in this writer, the operation will be changed to DatastoreBatchWriter.put(com.google.cloud.datastore.FullEntity<?>).

        Example of adding a single entity.

        
         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();
         
        Specified by:
        add in interface DatastoreBatchWriter
        Specified by:
        add in interface DatastoreWriter
        Parameters:
        entity - the entity to add
        Returns:
        an Entity with the same properties and a key that is either newly allocated or the same one if key is already complete
        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
      • add

        List<Entity> add​(FullEntity<?>... entities)
        Datastore add operation: inserts the provided entities. This method will automatically allocate id for any entity with an incomplete key. For entities with complete keys that were marked for deletion in this writer the operation will be changed to DatastoreBatchWriter.put(com.google.cloud.datastore.FullEntity<?>).

        Example of adding multiple entities.

        
         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();
         
        Specified by:
        add in interface DatastoreBatchWriter
        Specified by:
        add in interface DatastoreWriter
        Returns:
        a list of Entity ordered by input with the same properties and a key that is either newly allocated or the same one if was already complete
        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
        See Also:
        DatastoreWriter.add(FullEntity)
      • update

        void update​(Entity... entities)
        A Datastore update operation. The operation will fail if an entity with the same key does not already exist. This operation will be converted to DatastoreBatchWriter.put(com.google.cloud.datastore.FullEntity<?>) operation for entities that were already added or put in this writer. This operation will be converted to put(com.google.cloud.datastore.FullEntity<?>) operation for entities that were already added or put in this writer.

        Example of updating multiple entities.

        
         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();
         
        Specified by:
        update in interface DatastoreBatchWriter
        Specified by:
        update in interface DatastoreWriter
        Throws:
        DatastoreException - if an entity is marked for deletion in this transaction or if the transaction is no longer active
      • delete

        void delete​(Key... keys)
        A datastore delete operation. It is OK to request the deletion of a non-existing key. This operation will also remove from this batch any prior writes for entities with the same keys. This operation will also remove from this transaction any prior writes for entities with the same keys.

        Example of deleting multiple entities.

        
         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();
         
        Specified by:
        delete in interface DatastoreBatchWriter
        Specified by:
        delete in interface DatastoreWriter
        Throws:
        DatastoreException - upon failure or if no longer active
      • putWithDeferredIdAllocation

        void putWithDeferredIdAllocation​(FullEntity<?>... entities)
        Datastore put operation. This method will also allocate id for any entity with an incomplete key. As opposed to put(FullEntity) and put(FullEntity...), this method will defer any necessary id allocation to commit time.

        Example of putting multiple entities with deferred id allocation.

        
         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();
         
        Specified by:
        putWithDeferredIdAllocation in interface DatastoreBatchWriter
        Throws:
        IllegalArgumentException - if any of the given entities is missing a key
        DatastoreException - if no longer active
      • put

        Entity put​(FullEntity<?> entity)
        A Datastore put (a.k.a upsert) operation: inserts an entity if it does not exist, updates it otherwise. This method will automatically allocate an id if necessary. This operation will also remove from this writer any prior writes for the same entity. This operation will also remove from this transaction any prior writes for the same entity.

        Example of putting a single entity.

        
         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();
         
        Specified by:
        put in interface DatastoreBatchWriter
        Specified by:
        put in interface DatastoreWriter
        Parameters:
        entity - the entity to put
        Returns:
        an Entity with the same properties and a key that is either newly allocated or the same one if key is already complete
        Throws:
        DatastoreException - if id allocation for an entity with an incomplete key failed or if the transaction is no longer active
      • put

        List<Entity> put​(FullEntity<?>... entities)
        A Datastore put (a.k.a upsert) operation: creates an entity if it does not exist, updates it otherwise. This method will automatically allocate id for any entity with an incomplete key. This operation will also remove from this writer any prior writes for the same entities. This operation will also remove from this transaction any prior writes for the same entities.

        Example of putting multiple entities.

        
         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();
         
        Specified by:
        put in interface DatastoreBatchWriter
        Specified by:
        put in interface DatastoreWriter
        Returns:
        a list of updated or inserted Entity, ordered by input. Returned keys are either newly allocated or the same one if was already complete.
        Throws:
        DatastoreException - if id allocation for an entity with an incomplete key failed or if the transaction is no longer active
      • commit

        Transaction.Response commit()
        Commit the transaction.

        Example of committing a transaction.

        
         // 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
      • rollback

        void rollback()
        Rollback the transaction.

        Example of rolling back a transaction.

        
         // 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
      • isActive

        boolean isActive()
        Returns true if the transaction is still active (was not committed or rolledback).

        Example of verifying if a transaction is active.

        
         // 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();
           }
         }
         
        Specified by:
        isActive in interface DatastoreBatchWriter
      • getTransactionId

        com.google.protobuf.ByteString getTransactionId()