@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; } });
/** Example of using {@link TransactionManager}. */ // [TARGET transactionManager()] // [VARIABLE my_singer_id] public void transactionManager(final long singerId) throws InterruptedException { // [START transactionManager] try (TransactionManager manager = dbClient.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()).build()); try { manager.commit(); break; } catch (AbortedException e) { Thread.sleep(e.getRetryDelayInMillis() / 1000); txn = manager.resetForRetry(); } } } // [END transactionManager] } }
@Test public void updateEmpty() { Mutation m = Mutation.newUpdateBuilder("T2").build(); assertThat(m.getTable()).isEqualTo("T2"); assertThat(m.getOperation()).isEqualTo(Mutation.Op.UPDATE); assertThat(m.getColumns()).isEmpty(); assertThat(m.getValues()).isEmpty(); assertThat(m.toString()).isEqualTo("update(T2{})"); }
@Test public void update() { Mutation m = Mutation.newUpdateBuilder("T1").set("C1").to(true).set("C2").to(1234).build(); assertThat(m.getTable()).isEqualTo("T1"); assertThat(m.getOperation()).isEqualTo(Mutation.Op.UPDATE); assertThat(m.getColumns()).containsExactly("C1", "C2").inOrder(); assertThat(m.getValues()).containsExactly(Value.bool(true), Value.int64(1234)).inOrder(); assertThat(m.toString()).isEqualTo("update(T1{C1=true,C2=1234})"); }
Arrays.asList( Mutation.newInsertBuilder("T").set("C").to("V").build(), Mutation.newUpdateBuilder("T").set("C").to("V").build(), Mutation.newInsertOrUpdateBuilder("T").set("C").to("V").build(), Mutation.newReplaceBuilder("T").set("C").to("V").build(),
@Override public Long run(TransactionContext transaction) throws SpannerException { Struct row = strategy.read(transaction, key); long newValue = row.getLong(0) + 1; transaction.buffer( Mutation.newUpdateBuilder("T").set("K").to(key).set("V").to(newValue).build()); commitBarrier.countDown(); // Synchronize so that all threads attempt to commit at the same time. Uninterruptibles.awaitUninterruptibly(commitBarrier); return newValue; } };
@Test public void toProtoCoalescingChangeOfOperation() { List<Mutation> mutations = Arrays.asList( Mutation.newInsertBuilder("T").set("C").to("V1").build(), Mutation.newInsertBuilder("T").set("C").to("V2").build(), Mutation.newInsertBuilder("T").set("C").to("V3").build(), Mutation.newUpdateBuilder("T").set("C").to("V4").build(), Mutation.newUpdateBuilder("T").set("C").to("V5").build()); List<com.google.spanner.v1.Mutation> proto = new ArrayList<>(); Mutation.toProto(mutations, proto); assertThat(proto.size()).isEqualTo(2); MatcherAssert.assertThat( proto.get(0), matchesProto( "insert { table: 'T' columns: 'C' values { values { string_value: 'V1' } }" + " values { values { string_value: 'V2' } }" + " values { values { string_value: 'V3' } } }")); MatcherAssert.assertThat( proto.get(1), matchesProto( "update { table: 'T' columns: 'C' values { values { string_value: 'V4' } }" + " values { values { string_value: 'V5' } } }")); }
Mutation.newUpdateBuilder("T").set("K").to("Key3").set("BoolValue").to(false).build()); manager1.commit(); Mutation.newUpdateBuilder("T").set("K").to("Key3").set("BoolValue").to(true).build()); manager2.commit(); Struct row = client.singleUse().readRow("T", Key.of("Key3"), Arrays.asList("K", "BoolValue"));
static void update(DatabaseClient dbClient) { // Mutation can be used to update/insert/delete a single row in a table. Here we use // newUpdateBuilder to create update mutations. List<Mutation> mutations = Arrays.asList( Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(1) .set("AlbumId") .to(1) .set("MarketingBudget") .to(100000) .build(), Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(2) .set("AlbumId") .to(2) .set("MarketingBudget") .to(500000) .build()); // This writes all the mutations to Cloud Spanner atomically. dbClient.write(mutations); } // [END spanner_update_data]
@Test public void equalsAndHashCode() { EqualsTester tester = new EqualsTester(); // Equality, not identity. tester.addEqualityGroup( Mutation.newInsertBuilder("T1").build(), Mutation.newInsertBuilder("T1").build()); // Operation types are distinguished. tester.addEqualityGroup(Mutation.newInsertOrUpdateBuilder("T1").build()); tester.addEqualityGroup(Mutation.newUpdateBuilder("T1").build()); tester.addEqualityGroup(Mutation.newReplaceBuilder("T1").build()); // Table is distinguished. tester.addEqualityGroup(Mutation.newInsertBuilder("T2").build()); // Columns/values are distinguished (but by equality, not identity). tester.addEqualityGroup( Mutation.newInsertBuilder("T1").set("C").to("V").build(), Mutation.newInsertBuilder("T1").set("C").to("V").build()); // Deletes consider the key set. tester.addEqualityGroup(Mutation.delete("T1", KeySet.all())); tester.addEqualityGroup( Mutation.delete("T1", KeySet.singleKey(Key.of("k"))), Mutation.delete("T1", Key.of("k"))); tester.testEquals(); }
static void updateWithTimestamp(DatabaseClient dbClient) { // Mutation can be used to update/insert/delete a single row in a table. Here we use // newUpdateBuilder to create update mutations. List<Mutation> mutations = Arrays.asList( Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(1) .set("AlbumId") .to(1) .set("MarketingBudget") .to(1000000) .set("LastUpdateTime") .to(Value.COMMIT_TIMESTAMP) .build(), Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(2) .set("AlbumId") .to(2) .set("MarketingBudget") .to(750000) .set("LastUpdateTime") .to(Value.COMMIT_TIMESTAMP) .build()); // This writes all the mutations to Cloud Spanner atomically. dbClient.write(mutations); } // [END spanner_update_data_with_timestamp_column]
album2Budget -= transfer; transaction.buffer( Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(1) .build()); transaction.buffer( Mutation.newUpdateBuilder("Albums") .set("SingerId") .to(2)
@Override public MutationGroup apply(String userId) { // Immediately block the user. Mutation userMutation = Mutation.newUpdateBuilder("Users") .set("id").to(userId) .set("state").to("BLOCKED") .build(); long generatedId = Hashing.sha1().newHasher() .putString(userId, Charsets.UTF_8) .putLong(timestamp.getSeconds()) .putLong(timestamp.getNanos()) .hash() .asLong(); // Add an entry to pending review requests. Mutation pendingReview = Mutation.newInsertOrUpdateBuilder("PendingReviews") .set("id").to(generatedId) // Must be deterministically generated. .set("userId").to(userId) .set("action").to("REVIEW ACCOUNT") .set("note").to("Suspicious activity detected.") .build(); return MutationGroup.create(userMutation, pendingReview); } }));
@Test public void javaSerialization() throws Exception { reserializeAndAssert(appendAllTypes(Mutation.newInsertBuilder("test")).build()); reserializeAndAssert(appendAllTypes(Mutation.newUpdateBuilder("test")).build()); reserializeAndAssert(appendAllTypes(Mutation.newReplaceBuilder("test")).build()); reserializeAndAssert(appendAllTypes(Mutation.newInsertOrUpdateBuilder("test")).build());
private WriteBuilder writeBuilder(Op op, String tableName) { Mutation.WriteBuilder builder = null; switch (op) { case INSERT: builder = Mutation.newInsertBuilder(tableName); break; case INSERT_OR_UPDATE: builder = Mutation.newInsertOrUpdateBuilder(tableName); break; case UPDATE: builder = Mutation.newUpdateBuilder(tableName); break; } if (builder == null) { throw new IllegalArgumentException( "Unsupported save-mutation operation: " + op); } return builder; } }
private WriteBuilder writeBuilder(Op op, String tableName) { Mutation.WriteBuilder builder = null; switch (op) { case INSERT: builder = Mutation.newInsertBuilder(tableName); break; case INSERT_OR_UPDATE: builder = Mutation.newInsertOrUpdateBuilder(tableName); break; case UPDATE: builder = Mutation.newUpdateBuilder(tableName); break; } if (builder == null) { throw new IllegalArgumentException( "Unsupported save-mutation operation: " + op); } return builder; } }