@NotThreadSafe public interface Transaction extends DatastoreBatchWriter, DatastoreReaderWriter
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();
}
}
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.
Modifier and Type | Interface and Description |
---|---|
static interface |
Transaction.Response |
Modifier and Type | Method and Description |
---|---|
List<Entity> |
add(FullEntity<?>... entities)
Datastore add operation: inserts the provided entities.
|
Entity |
add(FullEntity<?> entity)
Datastore add operation: inserts the provided entity.
|
void |
addWithDeferredIdAllocation(FullEntity<?>... entities)
Datastore add operation.
|
Transaction.Response |
commit()
Commit the transaction.
|
void |
delete(Key... keys)
A datastore delete operation.
|
List<Entity> |
fetch(Key... keys)
Returns a list with a value for each given key (ordered by input).
|
Iterator<Entity> |
get(Key... key)
|
Entity |
get(Key key)
|
Datastore |
getDatastore()
Returns the transaction associated
Datastore . |
com.google.protobuf.ByteString |
getTransactionId() |
boolean |
isActive()
Returns
true if the transaction is still active (was not committed or rolledback). |
List<Entity> |
put(FullEntity<?>... entities)
A Datastore put (a.k.a upsert) operation: creates an entity if it does not exist, updates it
otherwise.
|
Entity |
put(FullEntity<?> entity)
A Datastore put (a.k.a upsert) operation: inserts an entity if it does not exist, updates it
otherwise.
|
void |
putWithDeferredIdAllocation(FullEntity<?>... entities)
Datastore put operation.
|
void |
rollback()
Rollback the transaction.
|
<T> QueryResults<T> |
run(Query<T> query)
Submits a
Query and returns its result. |
void |
update(Entity... entities)
A Datastore update operation.
|
runAggregation
Entity get(Key key)
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
get
in interface DatastoreReader
DatastoreException
- upon failure or if no longer activeIterator<Entity> get(Key... key)
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();
get
in interface DatastoreReader
DatastoreException
- upon failure or if no longer activeDatastoreReader.get(Key)
List<Entity> fetch(Key... keys)
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();
fetch
in interface DatastoreReader
DatastoreException
- upon failure or if no longer active<T> QueryResults<T> run(Query<T> query)
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();
run
in interface DatastoreReader
DatastoreException
- upon failure or if no longer activevoid addWithDeferredIdAllocation(FullEntity<?>... entities)
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();
addWithDeferredIdAllocation
in interface DatastoreBatchWriter
DatastoreException
- if a given entity with a complete key was already added to this
transaction or if the transaction is no longer activeEntity add(FullEntity<?> entity)
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();
add
in interface DatastoreBatchWriter
add
in interface DatastoreWriter
entity
- the entity to addEntity
with the same properties and a key that is either newly allocated or
the same one if key is already completeDatastoreException
- 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 failedList<Entity> add(FullEntity<?>... entities)
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();
add
in interface DatastoreBatchWriter
add
in interface DatastoreWriter
Entity
ordered by input with the same properties and a key that is
either newly allocated or the same one if was already completeDatastoreException
- 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 failedDatastoreWriter.add(FullEntity)
void update(Entity... entities)
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();
update
in interface DatastoreBatchWriter
update
in interface DatastoreWriter
DatastoreException
- if an entity is marked for deletion in this transaction or if the
transaction is no longer activevoid delete(Key... 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();
delete
in interface DatastoreBatchWriter
delete
in interface DatastoreWriter
DatastoreException
- upon failure or if no longer activevoid putWithDeferredIdAllocation(FullEntity<?>... entities)
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();
putWithDeferredIdAllocation
in interface DatastoreBatchWriter
IllegalArgumentException
- if any of the given entities is missing a keyDatastoreException
- if no longer activeEntity put(FullEntity<?> 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();
put
in interface DatastoreBatchWriter
put
in interface DatastoreWriter
entity
- the entity to putEntity
with the same properties and a key that is either newly allocated or
the same one if key is already completeDatastoreException
- if id allocation for an entity with an incomplete key failed or if
the transaction is no longer activeList<Entity> put(FullEntity<?>... 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();
put
in interface DatastoreBatchWriter
put
in interface DatastoreWriter
Entity
, ordered by input. Returned keys are
either newly allocated or the same one if was already complete.DatastoreException
- if id allocation for an entity with an incomplete key failed or if
the transaction is no longer activeTransaction.Response commit()
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
}
DatastoreException
- if could not commit the transaction or if no longer activevoid rollback()
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
DatastoreException
- if transaction was already committedboolean isActive()
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();
}
}
isActive
in interface DatastoreBatchWriter
com.google.protobuf.ByteString getTransactionId()
Copyright © 2023 Google LLC. All rights reserved.