From 92805d7977acb7cd0583ed87d38890dbb9a1d94b Mon Sep 17 00:00:00 2001 From: Shobhit Gupta Date: Fri, 16 Jan 2026 09:51:36 +0530 Subject: [PATCH] docs: Add snippet for ReadLockMode configuration at client and transaction --- samples/snippets/pom.xml | 2 +- .../IsolationLevelAndReadLockModeSample.java | 115 ++++++++++++++++++ .../com/example/spanner/SpannerSample.java | 48 -------- 3 files changed, 116 insertions(+), 49 deletions(-) create mode 100644 samples/snippets/src/main/java/com/example/spanner/IsolationLevelAndReadLockModeSample.java diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 2f5f6636cfb..6f1e6a5b0c3 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -34,7 +34,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.73.0 pom import diff --git a/samples/snippets/src/main/java/com/example/spanner/IsolationLevelAndReadLockModeSample.java b/samples/snippets/src/main/java/com/example/spanner/IsolationLevelAndReadLockModeSample.java new file mode 100644 index 00000000000..ca2e1a9d751 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/IsolationLevelAndReadLockModeSample.java @@ -0,0 +1,115 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.spanner; + +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.SpannerOptions.Builder.DefaultReadWriteTransactionOptions; +import com.google.cloud.spanner.Statement; +import com.google.spanner.v1.TransactionOptions.IsolationLevel; +import com.google.spanner.v1.TransactionOptions.ReadWrite.ReadLockMode; + +public class IsolationLevelAndReadLockModeSample { + + // [START spanner_isolation_level] + static void isolationLevelSetting(DatabaseId db) { + // The isolation level specified at the client-level will be applied to all + // RW transactions. + DefaultReadWriteTransactionOptions transactionOptions = + DefaultReadWriteTransactionOptions.newBuilder() + .setIsolationLevel(IsolationLevel.SERIALIZABLE) + .build(); + SpannerOptions options = + SpannerOptions.newBuilder() + .setDefaultTransactionOptions(transactionOptions) + .build(); + Spanner spanner = options.getService(); + DatabaseClient dbClient = spanner.getDatabaseClient(db); + dbClient + // The isolation level specified at the transaction-level takes precedence + // over the isolation level configured at the client-level. + .readWriteTransaction(Options.isolationLevel(IsolationLevel.REPEATABLE_READ)) + .run(transaction -> { + // Read an AlbumTitle. + String selectSql = + "SELECT AlbumTitle from Albums WHERE SingerId = 1 and AlbumId = 1"; + String title = null; + try (ResultSet resultSet = transaction.executeQuery(Statement.of(selectSql))) { + if (resultSet.next()) { + title = resultSet.getString("AlbumTitle"); + } + } + System.out.printf("Current album title: %s\n", title); + + // Update the title. + String updateSql = + "UPDATE Albums " + + "SET AlbumTitle = 'New Album Title' " + + "WHERE SingerId = 1 and AlbumId = 1"; + long rowCount = transaction.executeUpdate(Statement.of(updateSql)); + System.out.printf("%d record updated.\n", rowCount); + return null; + }); + } + // [END spanner_isolation_level] + + // [START spanner_read_lock_mode] + static void readLockModeSetting(DatabaseId db) { + // The read lock mode specified at the client-level will be applied to all + // RW transactions. + DefaultReadWriteTransactionOptions transactionOptions = + DefaultReadWriteTransactionOptions.newBuilder() + .setReadLockMode(ReadLockMode.OPTIMISTIC) + .build(); + SpannerOptions options = + SpannerOptions.newBuilder() + .setDefaultTransactionOptions(transactionOptions) + .build(); + Spanner spanner = options.getService(); + DatabaseClient dbClient = spanner.getDatabaseClient(db); + dbClient + // The read lock mode specified at the transaction-level takes precedence + // over the read lock mode configured at the client-level. + .readWriteTransaction(Options.readLockMode(ReadLockMode.PESSIMISTIC)) + .run(transaction -> { + // Read an AlbumTitle. + String selectSql = + "SELECT AlbumTitle from Albums WHERE SingerId = 1 and AlbumId = 1"; + String title = null; + try (ResultSet resultSet = transaction.executeQuery(Statement.of(selectSql))) { + if (resultSet.next()) { + title = resultSet.getString("AlbumTitle"); + } + } + System.out.printf("Current album title: %s\n", title); + + // Update the title. + String updateSql = + "UPDATE Albums " + + "SET AlbumTitle = 'New Album Title' " + + "WHERE SingerId = 1 and AlbumId = 1"; + long rowCount = transaction.executeUpdate(Statement.of(updateSql)); + System.out.printf("%d record updated.\n", rowCount); + return null; + }); + } + // [END spanner_read_lock_mode] +} \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java b/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java index 575d8068cb3..a01b00c0f6c 100644 --- a/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java @@ -32,7 +32,6 @@ import com.google.cloud.spanner.KeyRange; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; import com.google.cloud.spanner.ReadOnlyTransaction; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; @@ -40,7 +39,6 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.SpannerOptions.Builder.DefaultReadWriteTransactionOptions; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; @@ -73,7 +71,6 @@ import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; import com.google.spanner.admin.database.v1.RestoreInfo; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import com.google.spanner.v1.TransactionOptions.IsolationLevel; import java.math.BigDecimal; import java.time.Instant; import java.time.ZoneId; @@ -1555,47 +1552,6 @@ static void queryWithQueryOptions(DatabaseClient dbClient) { } // [END spanner_query_with_query_options] - // [START spanner_isolation_level] - static void isolationLevelSetting(DatabaseId db) { - // The isolation level specified at the client-level will be applied to all - // RW transactions. - DefaultReadWriteTransactionOptions transactionOptions = - DefaultReadWriteTransactionOptions.newBuilder() - .setIsolationLevel(IsolationLevel.SERIALIZABLE) - .build(); - SpannerOptions options = - SpannerOptions.newBuilder() - .setDefaultTransactionOptions(transactionOptions) - .build(); - Spanner spanner = options.getService(); - DatabaseClient dbClient = spanner.getDatabaseClient(db); - dbClient - // The isolation level specified at the transaction-level takes precedence - // over the isolation level configured at the client-level. - .readWriteTransaction(Options.isolationLevel(IsolationLevel.REPEATABLE_READ)) - .run(transaction -> { - // Read an AlbumTitle. - String selectSql = - "SELECT AlbumTitle from Albums WHERE SingerId = 1 and AlbumId = 1"; - ResultSet resultSet = transaction.executeQuery(Statement.of(selectSql)); - String title = null; - while (resultSet.next()) { - title = resultSet.getString("AlbumTitle"); - } - System.out.printf("Current album title: %s\n", title); - - // Update the title. - String updateSql = - "UPDATE Albums " - + "SET AlbumTitle = 'New Album Title' " - + "WHERE SingerId = 1 and AlbumId = 1"; - long rowCount = transaction.executeUpdate(Statement.of(updateSql)); - System.out.printf("%d record updated.\n", rowCount); - return null; - }); - } - // [END spanner_isolation_level] - // [START spanner_create_backup] static void createBackup(DatabaseAdminClient dbAdminClient, String projectId, String instanceId, String databaseId, String backupId, Timestamp versionTime) { @@ -2152,9 +2108,6 @@ static void run( case "querywithqueryoptions": queryWithQueryOptions(dbClient); break; - case "isolationlevelsettings": - isolationLevelSetting(database); - break; case "createbackup": createBackup(dbAdminClient, database.getInstanceId().getProject(), database.getInstanceId().getInstance(), database.getDatabase(), @@ -2265,7 +2218,6 @@ static void printUsageAndExit() { System.err.println(" SpannerExample querywithtimestampparameter my-instance example-db"); System.err.println(" SpannerExample clientwithqueryoptions my-instance example-db"); System.err.println(" SpannerExample querywithqueryoptions my-instance example-db"); - System.err.println(" SpannerExample isolationlevelsettings my-instance example-db"); System.err.println(" SpannerExample createbackup my-instance example-db"); System.err.println(" SpannerExample listbackups my-instance example-db"); System.err.println(" SpannerExample listbackupoperations my-instance example-db backup-id");