diff --git a/.kokoro/presubmit/samples.cfg b/.kokoro/presubmit/samples.cfg
new file mode 100644
index 00000000000..2cabe201bcd
--- /dev/null
+++ b/.kokoro/presubmit/samples.cfg
@@ -0,0 +1,38 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/java8"
+}
+
+env_vars: {
+ key: "JOB_TYPE"
+ value: "samples"
+}
+
+# TODO: remove this after we've migrated all tests and scripts
+env_vars: {
+ key: "GCLOUD_PROJECT"
+ value: "gcloud-devel"
+}
+
+env_vars: {
+ key: "GOOGLE_CLOUD_PROJECT"
+ value: "gcloud-devel"
+}
+
+env_vars: {
+ key: "GOOGLE_APPLICATION_CREDENTIALS"
+ value: "secret_manager/java-it-service-account"
+}
+
+env_vars: {
+ key: "SECRET_MANAGER_KEYS"
+ value: "java-it-service-account"
+}
+
+env_vars: {
+ key: "ENABLE_BUILD_COP"
+ value: "true"
+}
diff --git a/README.md b/README.md
index 165cf6ed2d5..24a1a9ca4c9 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
com.google.cloud
libraries-bom
- 26.57.0
+ 26.60.0
pom
import
@@ -41,7 +41,7 @@ If you are using Maven without the BOM, add this to your dependencies:
com.google.cloud
google-cloud-spanner
- 6.89.0
+ 6.93.0
```
@@ -575,6 +575,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
| Tag Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/TagSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/TagSample.java) |
| Tracing Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/TracingSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/TracingSample.java) |
| Transaction Timeout Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/TransactionTimeoutExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/TransactionTimeoutExample.java) |
+| Unnamed Parameters Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UnnamedParametersExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/UnnamedParametersExample.java) |
| Update Backup Schedule Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateBackupScheduleSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/UpdateBackupScheduleSample.java) |
| Update Database Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java) |
| Update Database With Default Leader Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java) |
diff --git a/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java b/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java
index 05c650dbfb7..390ac6c3b21 100644
--- a/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java
+++ b/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java
@@ -66,8 +66,7 @@ static void addSplitPoints(String projectId, String instanceId, String databaseI
com.google.spanner.admin.database.v1.SplitPoints splitPointForTable =
SplitPoints.newBuilder()
.setTable("Singers")
- .setKeys(
- 0,
+ .addKeys(
com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder()
.setKeyParts(
ListValue.newBuilder()
@@ -79,8 +78,7 @@ static void addSplitPoints(String projectId, String instanceId, String databaseI
com.google.spanner.admin.database.v1.SplitPoints splitPointForIndex =
SplitPoints.newBuilder()
.setIndex("SingersByFirstLastName")
- .setKeys(
- 0,
+ .addKeys(
com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder()
.setKeyParts(
ListValue.newBuilder()
@@ -93,16 +91,14 @@ static void addSplitPoints(String projectId, String instanceId, String databaseI
com.google.spanner.admin.database.v1.SplitPoints splitPointForIndexWitTableKey =
SplitPoints.newBuilder()
.setIndex("SingersByFirstLastName")
- .setKeys(
- 0,
+ .addKeys(
com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder()
.setKeyParts(
ListValue.newBuilder()
.addValues(Value.newBuilder().setStringValue("Jane").build())
.addValues(Value.newBuilder().setStringValue("Doe").build())
.build()))
- .setKeys(
- 1,
+ .addKeys(
com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder()
.setKeyParts(
ListValue.newBuilder()
diff --git a/samples/snippets/src/main/java/com/example/spanner/UnnamedParametersExample.java b/samples/snippets/src/main/java/com/example/spanner/UnnamedParametersExample.java
new file mode 100644
index 00000000000..3c73a7591d1
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/spanner/UnnamedParametersExample.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2025 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.Timestamp;
+import com.google.cloud.spanner.DatabaseClient;
+import com.google.cloud.spanner.DatabaseId;
+import com.google.cloud.spanner.ResultSet;
+import com.google.cloud.spanner.Spanner;
+import com.google.cloud.spanner.SpannerOptions;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.Statement.StatementFactory;
+import java.time.LocalDate;
+
+public class UnnamedParametersExample {
+
+ static void executeQueryWithUnnamedParameters() {
+ // TODO(developer): Replace these variables before running the sample.
+ String projectId = "my-project";
+ String instanceId = "my-instance";
+ String databaseId = "my-database";
+
+ executeQueryWithUnnamedParameters(projectId, instanceId, databaseId);
+ }
+
+ static void executeQueryWithUnnamedParameters(
+ String projectId, String instanceId, String databaseId) {
+ try (Spanner spanner =
+ SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
+
+ DatabaseClient client =
+ spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
+ StatementFactory statementFactory = client.getStatementFactory();
+
+ // Insert a row with unnamed parameters
+ client
+ .readWriteTransaction()
+ .run(
+ transaction -> {
+ Statement statement = statementFactory
+ .withUnnamedParameters("INSERT INTO Students(StudentId, Name, IsNRI, AvgMarks, "
+ + "JoinedAt, PinCode, CreatedAt) VALUES(?, ?, ?, ?, ?, ?, ?)",
+ 1000001,
+ "Google",
+ false,
+ (float) 34.5,
+ LocalDate.of(2024, 3, 31),
+ "123456",
+ Timestamp.now());
+ transaction.executeUpdate(statement);
+
+ return null;
+ });
+ System.out.println("Row is inserted.");
+
+ // Query the table with unnamed parameters
+ try (ResultSet resultSet =
+ client
+ .singleUse()
+ .executeQuery(
+ statementFactory.withUnnamedParameters(
+ "SELECT * FROM Students WHERE StudentId = ?", 1000001))) {
+ while (resultSet.next()) {
+ System.out.println(resultSet.getString("Name"));
+ }
+ }
+ System.out.println("Row is fetched.");
+ }
+ }
+}
diff --git a/samples/snippets/src/test/java/com/example/spanner/UnnamedParametersIT.java b/samples/snippets/src/test/java/com/example/spanner/UnnamedParametersIT.java
new file mode 100644
index 00000000000..d6c900dd60e
--- /dev/null
+++ b/samples/snippets/src/test/java/com/example/spanner/UnnamedParametersIT.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2025 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 static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.DatabaseId;
+import com.google.common.collect.ImmutableList;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UnnamedParametersIT extends SampleTestBase {
+ private static String databaseId;
+
+ @Before
+ public void setup() throws ExecutionException, InterruptedException {
+ databaseId = idGenerator.generateDatabaseId();
+ databaseAdminClient
+ .createDatabase(
+ databaseAdminClient
+ .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId))
+ .build(),
+ ImmutableList.of(
+ "CREATE TABLE Students ("
+ + " StudentId INT64 NOT NULL PRIMARY KEY,"
+ + " Name STRING(1024) NOT NULL,"
+ + " IsNRI BOOL NOT NULL,"
+ + " AvgMarks FLOAT32 NOT NULL,"
+ + " JoinedAt DATE NOT NULL,"
+ + " PinCode INT64 NOT NULL,"
+ + " CreatedAt TIMESTAMP NOT NULL"
+ + ")"))
+ .get();
+ }
+
+ @Test
+ public void testUnnamedParameters() throws Exception {
+ final String out =
+ SampleRunner.runSample(
+ () -> UnnamedParametersExample.executeQueryWithUnnamedParameters(projectId, instanceId,
+ databaseId));
+ assertTrue(out.contains("Row is inserted."));
+ assertTrue(out.contains("Google"));
+ assertTrue(out.contains("Row is fetched."));
+ }
+}