/** Example of a read write transaction. */ // [TARGET readWriteTransaction()] // [VARIABLE my_singer_id] public void readWriteTransaction(final long singerId) { // [START readWriteTransaction] TransactionRunner runner = dbClient.readWriteTransaction(); 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()).build()); return null; } }); // [END readWriteTransaction] }
@Override public Void run(TransactionContext transaction) throws SpannerException { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { return null; } }); return null; } });
private void doNestedRwTransaction() { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws SpannerException { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { return null; } }); return null; } }); }
@Override public void run() { client .readWriteTransaction() .run( new TransactionCallable<Void>() {
@Override public void run() { client .readWriteTransaction() .run( new TransactionCallable<Void>() {
private void executeQuery(long expectedCount, final String... stmts) { final TransactionCallable<Long> callable = new TransactionCallable<Long>() { @Override public Long run(TransactionContext transaction) { long rowCount = 0; for (final String stmt : stmts) { ResultSet resultSet = transaction.executeQuery(Statement.of(stmt)); assertThat(resultSet.next()).isFalse(); assertThat(resultSet.getStats()).isNotNull(); rowCount += resultSet.getStats().getRowCountExact(); } return rowCount; } }; TransactionRunner runner = client.readWriteTransaction(); Long rowCount = runner.run(callable); assertThat(rowCount).isEqualTo(expectedCount); }
private void executeUpdate(long expectedCount, final String... stmts) { final TransactionCallable<Long> callable = new TransactionCallable<Long>() { @Override public Long run(TransactionContext transaction) { long rowCount = 0; for (String stmt : stmts) { if (throwAbortOnce) { throwAbortOnce = false; throw SpannerExceptionFactory.newSpannerException( ErrorCode.ABORTED, "Abort in test"); } rowCount += transaction.executeUpdate(Statement.of(stmt)); } return rowCount; } }; TransactionRunner runner = client.readWriteTransaction(); Long rowCount = runner.run(callable); assertThat(rowCount).isEqualTo(expectedCount); }
@Test public void nestedTxnSucceedsWhenAllowed() { client .readWriteTransaction() .allowNestedTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws SpannerException { client.singleUseReadOnlyTransaction(); return null; } }); } }
@Test public void nestedReadOnlyTxnThrows() { try { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws SpannerException { client.readOnlyTransaction().getReadTimestamp(); return null; } }); fail("Expected exception"); } catch (SpannerException e) { assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INTERNAL); assertThat(e.getMessage()).contains("not supported"); } }
@Test public void nestedSingleUseReadTxnThrows() { try { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws SpannerException { client.singleUseReadOnlyTransaction(); return null; } }); fail("Expected exception"); } catch (SpannerException e) { assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INTERNAL); assertThat(e.getMessage()).contains("not supported"); } }
@Test public void standardDMLReadYourWrites() { executeUpdate(DML_COUNT, INSERT_DML); final TransactionCallable<Void> callable = new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) { long rowCount = transaction.executeUpdate(Statement.of("UPDATE T SET v = v * 2 WHERE k = 'boo2';")); assertThat(rowCount).isEqualTo(1); assertThat(transaction.readRow("T", Key.of("boo2"), Arrays.asList("v")).getLong(0)) .isEqualTo(2 * 2); return null; } }; TransactionRunner runner = client.readWriteTransaction(); runner.run(callable); executeUpdate(DML_COUNT, DELETE_DML); }
@Test public void nestedBatchTxnThrows() { try { client .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws SpannerException { BatchClient batchClient = env.getTestHelper().getBatchClient(db); BatchReadOnlyTransaction batchTxn = batchClient.batchReadOnlyTransaction(TimestampBound.strong()); batchTxn.partitionReadUsingIndex( PartitionOptions.getDefaultInstance(), "Test", "Index", KeySet.all(), Arrays.asList("Fingerprint")); return null; } }); fail("Expected exception"); } catch (SpannerException e) { assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INTERNAL); assertThat(e.getMessage()).contains("not supported"); } }
@Test public void userExceptionIsSpannerException() { final String key = uniqueKey(); TransactionCallable<Void> callable = new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) { transaction.buffer(Mutation.newInsertOrUpdateBuilder("T").set("K").to(key).build()); throw newSpannerException(ErrorCode.OUT_OF_RANGE, "User failure"); } }; try { client.readWriteTransaction().run(callable); fail("Expected user exception"); } catch (SpannerException e) { assertThat(e.getErrorCode()).isEqualTo(ErrorCode.OUT_OF_RANGE); assertThat(e.getMessage()).contains("User failure"); } Struct row = client.singleUse(TimestampBound.strong()).readRow("T", Key.of(key), Arrays.asList("K")); assertThat(row).isNull(); }
@Test public void userExceptionPreventsCommit() { class UserException extends Exception { UserException(String message) { super(message); } } final String key = uniqueKey(); TransactionCallable<Void> callable = new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws UserException { transaction.buffer(Mutation.newInsertOrUpdateBuilder("T").set("K").to(key).build()); throw new UserException("User failure"); } }; try { client.readWriteTransaction().run(callable); fail("Expected user exception"); } catch (SpannerException e) { assertThat(e.getErrorCode()).isEqualTo(ErrorCode.UNKNOWN); assertThat(e.getMessage()).contains("User failure"); assertThat(e.getCause()).isInstanceOf(UserException.class); } Struct row = client.singleUse(TimestampBound.strong()).readRow("T", Key.of(key), Arrays.asList("K")); assertThat(row).isNull(); }
TransactionRunner runner = client.readWriteTransaction(); runner.run(callable); fail("Expected user exception");
static void deleteUsingDml(DatabaseClient dbClient) { dbClient .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String sql = "DELETE FROM Singers WHERE FirstName = 'Alice'"; long rowCount = transaction.executeUpdate(Statement.of(sql)); System.out.printf("%d record deleted.\n", rowCount); return null; } }); } // [END spanner_dml_standard_delete]
static void insertUsingDml(DatabaseClient dbClient) { dbClient .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String sql = "INSERT INTO Singers (SingerId, FirstName, LastName) " + " VALUES (10, 'Virginia', 'Watson')"; long rowCount = transaction.executeUpdate(Statement.of(sql)); System.out.printf("%d record inserted.\n", rowCount); return null; } }); } // [END spanner_dml_standard_insert]
static void updateUsingDmlWithTimestamp(DatabaseClient dbClient) { dbClient .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String sql = "UPDATE Albums " + "SET LastUpdateTime = PENDING_COMMIT_TIMESTAMP() WHERE SingerId = 1"; long rowCount = transaction.executeUpdate(Statement.of(sql)); System.out.printf("%d records updated.\n", rowCount); return null; } }); } // [END spanner_dml_standard_update_with_timestamp]
static void updateUsingDml(DatabaseClient dbClient) { dbClient .readWriteTransaction() .run( new TransactionCallable<Void>() { @Override public Void run(TransactionContext transaction) throws Exception { String sql = "UPDATE Albums " + "SET MarketingBudget = MarketingBudget * 2 " + "WHERE SingerId = 1 and AlbumId = 1"; long rowCount = transaction.executeUpdate(Statement.of(sql)); System.out.printf("%d record updated.\n", rowCount); return null; } }); } // [END spanner_dml_standard_update]
TransactionRunner runner = client.readWriteTransaction(); runner.run(callable);