Class DatabaseClientWithChangeSets
- java.lang.Object
-
- com.google.cloud.spanner.watcher.DatabaseClientWithChangeSets
-
- All Implemented Interfaces:
com.google.cloud.spanner.DatabaseClient
public class DatabaseClientWithChangeSets extends Object implements com.google.cloud.spanner.DatabaseClient
A wrapper around aDatabaseClientthat automatically generates change set id's and adds a mutation for a change set for each read/write transaction. ThisDatabaseClientcan be used in combination withSpannerTableChangeSetPollerorSpannerDatabaseChangeSetPollerto trigger data changed events for tables that do not contain a commit timestamp column.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interfaceDatabaseClientWithChangeSets.AsyncRunnerWithChangeSetAsyncRunnerthat automatically creates a change set.static interfaceDatabaseClientWithChangeSets.AsyncTransactionManagerWithChangeSetAsyncTransactionManagerthat automatically creates a change set.static interfaceDatabaseClientWithChangeSets.ChangeSetIdGeneratorInterface for generating unique id's for change sets.static interfaceDatabaseClientWithChangeSets.ChangeSetIdSupplierSupplier of change set id's.static interfaceDatabaseClientWithChangeSets.TransactionManagerWithChangeSetTransactionManagerthat automatically creates a change set.static interfaceDatabaseClientWithChangeSets.TransactionRunnerWithChangeSetTransactionRunnerthat automatically creates a change set.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description longexecutePartitionedUpdate(com.google.cloud.spanner.Statement stmt, com.google.cloud.spanner.Options.UpdateOption... options)StringnewChangeSetId()static DatabaseClientWithChangeSetsof(com.google.cloud.spanner.DatabaseClient client)Creates aDatabaseClientthat will automatically create a change set for each read/write transaction.com.google.cloud.spanner.ReadOnlyTransactionreadOnlyTransaction()com.google.cloud.spanner.ReadOnlyTransactionreadOnlyTransaction(com.google.cloud.spanner.TimestampBound bound)DatabaseClientWithChangeSets.TransactionRunnerWithChangeSetreadWriteTransaction(com.google.cloud.spanner.Options.TransactionOption... options)Creates aTransactionRunnerthat automatically creates a change set.DatabaseClientWithChangeSets.AsyncRunnerWithChangeSetrunAsync(com.google.cloud.spanner.Options.TransactionOption... options)Returns an asynchronous transaction runner that automatically creates a change set for executing a single logical transaction with retries.com.google.cloud.spanner.ReadContextsingleUse()com.google.cloud.spanner.ReadContextsingleUse(com.google.cloud.spanner.TimestampBound bound)com.google.cloud.spanner.ReadOnlyTransactionsingleUseReadOnlyTransaction()com.google.cloud.spanner.ReadOnlyTransactionsingleUseReadOnlyTransaction(com.google.cloud.spanner.TimestampBound bound)DatabaseClientWithChangeSets.TransactionManagerWithChangeSettransactionManager(com.google.cloud.spanner.Options.TransactionOption... options)Returns a transaction manager that automatically creates a change set.DatabaseClientWithChangeSets.AsyncTransactionManagerWithChangeSettransactionManagerAsync(com.google.cloud.spanner.Options.TransactionOption... options)Returns an asynchronous transaction manager that automatically creates a change set, and which allows manual management of transaction lifecycle.com.google.cloud.Timestampwrite(Iterable<com.google.cloud.spanner.Mutation> mutations)Writes the given mutations WITHOUT a change set id.com.google.cloud.Timestampwrite(String changeSetId, Iterable<com.google.cloud.spanner.Mutation> mutations)Writes the given mutations atomically to the database using the given change set id.com.google.cloud.TimestampwriteAtLeastOnce(Iterable<com.google.cloud.spanner.Mutation> mutations)Writes the given mutations WITHOUT a change set id.com.google.cloud.TimestampwriteAtLeastOnce(String changeSetId, Iterable<com.google.cloud.spanner.Mutation> mutations)Writes the given mutations atomically to the database without replay protection using the given change set id.com.google.cloud.spanner.CommitResponsewriteAtLeastOnceWithOptions(Iterable<com.google.cloud.spanner.Mutation> mutations, com.google.cloud.spanner.Options.TransactionOption... options)com.google.cloud.spanner.CommitResponsewriteWithOptions(Iterable<com.google.cloud.spanner.Mutation> mutations, com.google.cloud.spanner.Options.TransactionOption... options)
-
-
-
Method Detail
-
of
public static DatabaseClientWithChangeSets of(com.google.cloud.spanner.DatabaseClient client)
Creates aDatabaseClientthat will automatically create a change set for each read/write transaction.
-
newChangeSetId
public String newChangeSetId()
-
write
public com.google.cloud.Timestamp write(Iterable<com.google.cloud.spanner.Mutation> mutations) throws com.google.cloud.spanner.SpannerException
Writes the given mutations WITHOUT a change set id. Consider usingwrite(String, Iterable).- Specified by:
writein interfacecom.google.cloud.spanner.DatabaseClient- Throws:
com.google.cloud.spanner.SpannerException
-
write
public com.google.cloud.Timestamp write(String changeSetId, Iterable<com.google.cloud.spanner.Mutation> mutations) throws com.google.cloud.spanner.SpannerException
Writes the given mutations atomically to the database using the given change set id.This method uses retries and replay protection internally, which means that the mutations are applied exactly once on success, or not at all if an error is returned, regardless of any failures in the underlying network. Note that if the call is cancelled or reaches deadline, it is not possible to know whether the mutations were applied without performing a subsequent database operation, but the mutations will have been applied at most once.
Example of blind write.
String changeSetId = dbClient.newChangeSetId(); long singerId = my_singer_id; Mutation mutation = Mutation.newInsertBuilder("Singer") .set("SingerId") .to(singerId) .set("FirstName") .to("Billy") .set("LastName") .to("Joel") .set("ChangeSetId") .to(changeSetId) .build(); dbClient.write(Collections.singletonList(mutation));- Returns:
- the timestamp at which the write was committed
- Throws:
com.google.cloud.spanner.SpannerException
-
writeAtLeastOnce
public com.google.cloud.Timestamp writeAtLeastOnce(Iterable<com.google.cloud.spanner.Mutation> mutations) throws com.google.cloud.spanner.SpannerException
Writes the given mutations WITHOUT a change set id. Consider usingwriteAtLeastOnce(String, Iterable).- Specified by:
writeAtLeastOncein interfacecom.google.cloud.spanner.DatabaseClient- Throws:
com.google.cloud.spanner.SpannerException
-
writeAtLeastOnce
public com.google.cloud.Timestamp writeAtLeastOnce(String changeSetId, Iterable<com.google.cloud.spanner.Mutation> mutations) throws com.google.cloud.spanner.SpannerException
Writes the given mutations atomically to the database without replay protection using the given change set id.Since this method does not feature replay protection, it may attempt to apply
mutationsmore than once; if the mutations are not idempotent, this may lead to a failure being reported when the mutation was applied once. For example, an insert may fail withErrorCode.ALREADY_EXISTSeven though the row did not exist before this method was called. For this reason, most users of the library will prefer to usewrite(Iterable)instead. However,writeAtLeastOnce()requires only a single RPC, whereaswrite()requires two RPCs (one of which may be performed in advance), and so this method may be appropriate for latency sensitive and/or high throughput blind writing.Example of unprotected blind write.
String changeSetId = dbClient.newChangeSetId(); long singerId = my_singer_id; Mutation mutation = Mutation.newInsertBuilder("Singers") .set("SingerId") .to(singerId) .set("FirstName") .to("Billy") .set("LastName") .to("Joel") .set("ChangeSetId") .to(changeSetId) .build(); dbClient.writeAtLeastOnce(changeSetId, Collections.singletonList(mutation));- Returns:
- the timestamp at which the write was committed
- Throws:
com.google.cloud.spanner.SpannerException
-
readWriteTransaction
public DatabaseClientWithChangeSets.TransactionRunnerWithChangeSet readWriteTransaction(com.google.cloud.spanner.Options.TransactionOption... options)
Creates aTransactionRunnerthat automatically creates a change set.Example usage:
DatabaseClientWithChangeSets dbClientWithChangeSets = DatabaseClientWithChangeSets.of(dbClient); TransactionRunnerWithChangeSet runner = dbClientWithChangeSets.readWriteTransaction(); long singerId = my_singer_id; runner.run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String column = "FirstName"; Struct row = transaction.readRow("Singers", Key.of(singerId), Collections.singleton(column)); String name = row.getString(column); transaction.buffer( Mutation.newUpdateBuilder("Singers") .set(column).to(name.toUpperCase()) .set("ChangeSetId").to(runner.getChangeSetId()) .build()); return null; } });- Specified by:
readWriteTransactionin interfacecom.google.cloud.spanner.DatabaseClient
-
transactionManager
public DatabaseClientWithChangeSets.TransactionManagerWithChangeSet transactionManager(com.google.cloud.spanner.Options.TransactionOption... options)
Returns a transaction manager that automatically creates a change set. This API is meant for advanced users. Most users should instead use the#readWriteTransaction()API instead.Example usage:
DatabaseClientWithChangeSets dbClientWithChangeSets = DatabaseClientWithChangeSets.of(dbClient); long singerId = my_singer_id; try (TransactionManagerWithChangeSet manager = dbClientWithChangeSets.transactionManager()) { TransactionContext txn = manager.begin(); while (true) { String column = "FirstName"; Struct row = txn.readRow("Singers", Key.of(singerId), Collections.singleton(column)); String name = row.getString(column); txn.buffer( Mutation.newUpdateBuilder("Singers") .set(column).to(name.toUpperCase()) .set("ChangeSetId").to(manager.getChangeSetId()) .build()); try { manager.commit(); break; } catch (AbortedException e) { Thread.sleep(e.getRetryDelayInMillis() / 1000); txn = manager.resetForRetry(); } } }- Specified by:
transactionManagerin interfacecom.google.cloud.spanner.DatabaseClient
-
runAsync
public DatabaseClientWithChangeSets.AsyncRunnerWithChangeSet runAsync(com.google.cloud.spanner.Options.TransactionOption... options)
Returns an asynchronous transaction runner that automatically creates a change set for executing a single logical transaction with retries. The returned runner can only be used once.Example usage:
Executor executor = Executors.newSingleThreadExecutor(); DatabaseClientWithChangeSets dbClientWithChangeSets = DatabaseClientWithChangeSets.of(dbClient); final long singerId = my_singer_id; AsyncRunnerWithChangeSet runner = dbClientWithChangeSets.runAsync(); ApiFuturerowCount = runner.runAsync( new AsyncWork () { - Specified by:
runAsyncin interfacecom.google.cloud.spanner.DatabaseClient
-
transactionManagerAsync
public DatabaseClientWithChangeSets.AsyncTransactionManagerWithChangeSet transactionManagerAsync(com.google.cloud.spanner.Options.TransactionOption... options)
Returns an asynchronous transaction manager that automatically creates a change set, and which allows manual management of transaction lifecycle. This API is meant for advanced users. Most users should instead use the#runAsync()API instead.Example of using
DatabaseClientWithChangeSets.AsyncTransactionManagerWithChangeSetwith lambda expressions (Java 8 and higher).DatabaseClientWithChangeSets dbClientWithChangeSets = DatabaseClientWithChangeSets.of(dbClient); long singerId = 1L; try (AsyncTransactionManagerWithChangeSet manager = dbClientWithChangeSets.transactionManagerAsync()) { TransactionContextFuture txnFut = manager.beginAsync(); while (true) { String column = "FirstName"; CommitTimestampFuture commitTimestamp = txnFut .then( (txn, __) -> txn.readRowAsync( "Singers", Key.of(singerId), Collections.singleton(column))) .then( (txn, row) -> { String name = row.getString(column); txn.buffer( Mutation.newUpdateBuilder("Singers") .set(column) .to(name.toUpperCase()) .set("ChangeSetId") .to(manager.getChangeSetId()) .build()); return ApiFutures.immediateFuture(null); }) .commitAsync(); try { commitTimestamp.get(); break; } catch (AbortedException e) { Thread.sleep(e.getRetryDelayInMillis() / 1000); txnFut = manager.resetForRetryAsync(); } } }- Specified by:
transactionManagerAsyncin interfacecom.google.cloud.spanner.DatabaseClient
-
singleUse
public com.google.cloud.spanner.ReadContext singleUse()
- Specified by:
singleUsein interfacecom.google.cloud.spanner.DatabaseClient
-
singleUse
public com.google.cloud.spanner.ReadContext singleUse(com.google.cloud.spanner.TimestampBound bound)
- Specified by:
singleUsein interfacecom.google.cloud.spanner.DatabaseClient
-
singleUseReadOnlyTransaction
public com.google.cloud.spanner.ReadOnlyTransaction singleUseReadOnlyTransaction()
- Specified by:
singleUseReadOnlyTransactionin interfacecom.google.cloud.spanner.DatabaseClient
-
singleUseReadOnlyTransaction
public com.google.cloud.spanner.ReadOnlyTransaction singleUseReadOnlyTransaction(com.google.cloud.spanner.TimestampBound bound)
- Specified by:
singleUseReadOnlyTransactionin interfacecom.google.cloud.spanner.DatabaseClient
-
readOnlyTransaction
public com.google.cloud.spanner.ReadOnlyTransaction readOnlyTransaction()
- Specified by:
readOnlyTransactionin interfacecom.google.cloud.spanner.DatabaseClient
-
readOnlyTransaction
public com.google.cloud.spanner.ReadOnlyTransaction readOnlyTransaction(com.google.cloud.spanner.TimestampBound bound)
- Specified by:
readOnlyTransactionin interfacecom.google.cloud.spanner.DatabaseClient
-
executePartitionedUpdate
public long executePartitionedUpdate(com.google.cloud.spanner.Statement stmt, com.google.cloud.spanner.Options.UpdateOption... options)- Specified by:
executePartitionedUpdatein interfacecom.google.cloud.spanner.DatabaseClient
-
writeWithOptions
public com.google.cloud.spanner.CommitResponse writeWithOptions(Iterable<com.google.cloud.spanner.Mutation> mutations, com.google.cloud.spanner.Options.TransactionOption... options) throws com.google.cloud.spanner.SpannerException
- Specified by:
writeWithOptionsin interfacecom.google.cloud.spanner.DatabaseClient- Throws:
com.google.cloud.spanner.SpannerException
-
writeAtLeastOnceWithOptions
public com.google.cloud.spanner.CommitResponse writeAtLeastOnceWithOptions(Iterable<com.google.cloud.spanner.Mutation> mutations, com.google.cloud.spanner.Options.TransactionOption... options) throws com.google.cloud.spanner.SpannerException
- Specified by:
writeAtLeastOnceWithOptionsin interfacecom.google.cloud.spanner.DatabaseClient- Throws:
com.google.cloud.spanner.SpannerException
-
-