Skip to content

Commit 98ada18

Browse files
committed
Merge branch 'main' into PR #2113 to update
2 parents 432e32d + ce86181 commit 98ada18

File tree

13 files changed

+309
-17
lines changed

13 files changed

+309
-17
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Changelog
22

3+
## [2.33.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.0...v2.33.1) (2025-10-09)
4+
5+
6+
### Dependencies
7+
8+
* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.76.0 ([#2240](https://github.com/googleapis/java-spanner-jdbc/issues/2240)) ([442565e](https://github.com/googleapis/java-spanner-jdbc/commit/442565ea8bf22ee926126fbd11a68a869b0772c7))
9+
* Update dependency com.google.cloud:google-cloud-spanner to v6.101.1 ([#2227](https://github.com/googleapis/java-spanner-jdbc/issues/2227)) ([275c6bd](https://github.com/googleapis/java-spanner-jdbc/commit/275c6bd7f3f58b3f980e9ffaa576d1f910ecf08b))
10+
* Update dependency com.google.cloud:google-cloud-spanner to v6.102.0 ([#2244](https://github.com/googleapis/java-spanner-jdbc/issues/2244)) ([383a392](https://github.com/googleapis/java-spanner-jdbc/commit/383a39222c7526163323575734c8473a34d4098d))
11+
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.101.1 ([#2228](https://github.com/googleapis/java-spanner-jdbc/issues/2228)) ([ded7944](https://github.com/googleapis/java-spanner-jdbc/commit/ded79447b8ecd294e56560b43cb02e45464706f1))
12+
* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.102.0 ([#2246](https://github.com/googleapis/java-spanner-jdbc/issues/2246)) ([7162ac2](https://github.com/googleapis/java-spanner-jdbc/commit/7162ac236a77c24b4f0faccefa2cf3bdee6b96ab))
13+
* Update dependency com.google.cloud:google-cloud-trace to v2.76.0 ([#2241](https://github.com/googleapis/java-spanner-jdbc/issues/2241)) ([ff2432d](https://github.com/googleapis/java-spanner-jdbc/commit/ff2432d46cd23df2230671297f06c8e6fca8f1d7))
14+
* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.3 ([#2236](https://github.com/googleapis/java-spanner-jdbc/issues/2236)) ([9a44975](https://github.com/googleapis/java-spanner-jdbc/commit/9a44975e0ab7ca49514be1d9ea03e8e760a0f3bc))
15+
* Update dependency net.bytebuddy:byte-buddy to v1.17.8 ([#2245](https://github.com/googleapis/java-spanner-jdbc/issues/2245)) ([60a3a8f](https://github.com/googleapis/java-spanner-jdbc/commit/60a3a8f0fcf86742128f8803ee3297670b713923))
16+
* Update dependency net.bytebuddy:byte-buddy-agent to v1.17.8 ([#2243](https://github.com/googleapis/java-spanner-jdbc/issues/2243)) ([952c08a](https://github.com/googleapis/java-spanner-jdbc/commit/952c08afbf2f7838ad864b8bb58423e8b566d325))
17+
18+
19+
### Documentation
20+
21+
* Add samples for transaction isolation level ([#2030](https://github.com/googleapis/java-spanner-jdbc/issues/2030)) ([ca243d1](https://github.com/googleapis/java-spanner-jdbc/commit/ca243d194ef392d44cea561a148c0376b9af630d))
22+
323
## [2.33.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.3...v2.33.0) (2025-09-27)
424

525

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file:
2020
<dependency>
2121
<groupId>com.google.cloud</groupId>
2222
<artifactId>google-cloud-spanner-jdbc</artifactId>
23-
<version>2.33.0</version>
23+
<version>2.33.1</version>
2424
</dependency>
2525
```
2626
<!--- {x-version-update-end} -->
@@ -30,15 +30,15 @@ If you are using Gradle without BOM, add this to your dependencies
3030

3131
<!--- {x-version-update-start:google-cloud-spanner-jdbc:released} -->
3232
```Groovy
33-
implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.0'
33+
implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.1'
3434
```
3535
<!--- {x-version-update-end} -->
3636

3737
If you are using SBT, add this to your dependencies
3838

3939
<!--- {x-version-update-start:google-cloud-spanner-jdbc:released} -->
4040
```Scala
41-
libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.0"
41+
libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.1"
4242
```
4343
<!--- {x-version-update-end} -->
4444

@@ -109,6 +109,7 @@ See [Supported Connection Properties](documentation/connection_properties.md) fo
109109
supported connection properties.
110110

111111
#### Commonly Used Properties
112+
- default_isolation_level (String): Spanner supports isolation levels REPEATABLE_READ or SERIALIZABLE. SERIALIZABLE is the default. Using isolation level REPEATABLE_READ improves performance by reducing the amount of locks that are taken by transactions that execute a large number of queries in read/write transactions. See https://cloud.google.com/spanner/docs/isolation-levels for more information on the supported isolation levels in Spanner.
112113
- credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json`
113114
- autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true.
114115
- readonly (boolean): Sets the initial readonly mode for the connection. Default is false.

documentation/latency-debugging-guide.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,43 @@ queries and transactions and to determine whether transactions or requests are b
55
addition, all metrics described in [Latency points in a Spanner request](https://cloud.google.com/spanner/docs/latency-points)
66
are also collected by the JDBC driver and can be used for debugging.
77

8+
## Isolation Level
9+
10+
A common reason for high latency in read/write transactions is lock contention. Spanner by default
11+
uses isolation level `SERIALIZABLE`. This causes all queries in read/write transactions to take
12+
locks for all rows that are scanned by a query. Using isolation level `REPEATABLE_READ` reduces the
13+
number of locks that are taken during a read/write transaction, and can significantly improve
14+
performance for applications that execute many and/or large queries in read/write transactions.
15+
16+
Enable isolation level `REPEATABLE_READ` by default for all transactions that are executed by the
17+
JDBC driver by setting the `default_isolation_level` connection property like this in the connection
18+
URL:
19+
20+
```java
21+
String projectId = "my-project";
22+
String instanceId = "my-instance";
23+
String databaseId = "my-database";
24+
String isolationLevel = "REPEATABLE_READ";
25+
26+
try (Connection connection =
27+
DriverManager.getConnection(
28+
String.format(
29+
"jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?default_isolation_level=%s",
30+
projectId, instanceId, databaseId, isolationLevel))) {
31+
try (Statement statement = connection.createStatement()) {
32+
try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) {
33+
while (rs.next()) {
34+
System.out.printf(
35+
"Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString());
36+
}
37+
}
38+
}
39+
}
40+
```
41+
42+
See https://cloud.google.com/spanner/docs/isolation-levels for more information on the supported
43+
isolation levels in Spanner.
44+
845
## Configuration
946

1047
You can configure the OpenTelemetry instance that should be used in two ways:

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
66
<artifactId>google-cloud-spanner-jdbc</artifactId>
7-
<version>2.33.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner-jdbc:current} -->
7+
<version>2.33.2-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner-jdbc:current} -->
88
<packaging>jar</packaging>
99
<name>Google Cloud Spanner JDBC</name>
1010
<url>https://github.com/googleapis/java-spanner-jdbc</url>
@@ -61,7 +61,7 @@
6161
<dependency>
6262
<groupId>com.google.cloud</groupId>
6363
<artifactId>google-cloud-spanner-bom</artifactId>
64-
<version>6.101.1</version>
64+
<version>6.102.0</version>
6565
<type>pom</type>
6666
<scope>import</scope>
6767
</dependency>

samples/snapshot/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<dependency>
3030
<groupId>com.google.cloud</groupId>
3131
<artifactId>google-cloud-spanner-jdbc</artifactId>
32-
<version>2.33.1-SNAPSHOT</version>
32+
<version>2.33.2-SNAPSHOT</version>
3333
</dependency>
3434
<!-- {x-version-update-end} -->
3535

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner.jdbc;
18+
19+
import java.sql.Connection;
20+
import java.sql.DriverManager;
21+
import java.sql.PreparedStatement;
22+
import java.sql.ResultSet;
23+
import java.sql.SQLException;
24+
import java.util.Properties;
25+
26+
final class IsolationLevel {
27+
28+
static void isolationLevel(
29+
final String project,
30+
final String instance,
31+
final String database,
32+
final Properties properties)
33+
throws SQLException {
34+
String url = String.format(
35+
"jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
36+
project, instance, database);
37+
try (Connection connection = DriverManager.getConnection(url, properties)) {
38+
connection.setAutoCommit(false);
39+
40+
// Spanner supports setting the isolation level to:
41+
// 1. TRANSACTION_SERIALIZABLE (this is the default)
42+
// 2. TRANSACTION_REPEATABLE_READ
43+
44+
// The following line sets the default isolation level that will be used
45+
// for all read/write transactions on this connection.
46+
connection.setTransactionIsolation(
47+
Connection.TRANSACTION_REPEATABLE_READ);
48+
49+
// This query will not take any locks when using
50+
// isolation level repeatable read.
51+
try (ResultSet resultSet = connection
52+
.createStatement()
53+
.executeQuery("SELECT SingerId, Active "
54+
+ "FROM Singers "
55+
+ "ORDER BY LastName")) {
56+
while (resultSet.next()) {
57+
try (PreparedStatement statement = connection.prepareStatement(
58+
"INSERT OR UPDATE INTO SingerHistory "
59+
+ "(SingerId, Active, CreatedAt) "
60+
+ "VALUES (?, ?, CURRENT_TIMESTAMP)")) {
61+
statement.setLong(1, resultSet.getLong(1));
62+
statement.setBoolean(2, resultSet.getBoolean(2));
63+
statement.executeUpdate();
64+
}
65+
}
66+
}
67+
connection.commit();
68+
}
69+
}
70+
71+
private IsolationLevel() {
72+
}
73+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner.jdbc;
18+
19+
import static com.example.spanner.jdbc.IsolationLevel.isolationLevel;
20+
import static org.junit.Assume.assumeTrue;
21+
22+
import java.sql.Connection;
23+
import java.sql.DriverManager;
24+
import java.sql.SQLException;
25+
import java.sql.Statement;
26+
import java.util.Properties;
27+
import org.junit.AfterClass;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
import org.junit.runners.JUnit4;
32+
import org.testcontainers.DockerClientFactory;
33+
import org.testcontainers.containers.GenericContainer;
34+
import org.testcontainers.containers.wait.strategy.Wait;
35+
import org.testcontainers.images.PullPolicy;
36+
import org.testcontainers.utility.DockerImageName;
37+
38+
@RunWith(JUnit4.class)
39+
public class IsolationLevelTest {
40+
41+
private static GenericContainer<?> emulator;
42+
43+
private static final String PROJECT = "emulator-project";
44+
private static final String INSTANCE = "my-instance";
45+
private static final String DATABASE = "my-database";
46+
private static final Properties PROPERTIES = new Properties();
47+
48+
@BeforeClass
49+
public static void setupEmulator() throws Exception {
50+
assumeTrue("This test requires Docker", DockerClientFactory.instance().isDockerAvailable());
51+
52+
emulator =
53+
new GenericContainer<>(DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator"));
54+
emulator.withImagePullPolicy(PullPolicy.alwaysPull());
55+
emulator.addExposedPort(9010);
56+
emulator.setWaitStrategy(Wait.forListeningPorts(9010));
57+
emulator.start();
58+
59+
PROPERTIES.setProperty("endpoint",
60+
String.format("localhost:%d", emulator.getMappedPort(9010)));
61+
PROPERTIES.setProperty("autoConfigEmulator", "true");
62+
63+
String url = String.format(
64+
"jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
65+
PROJECT, INSTANCE, DATABASE);
66+
try (Connection connection = DriverManager.getConnection(url, PROPERTIES)) {
67+
try (Statement statement = connection.createStatement()) {
68+
statement.addBatch(
69+
"CREATE TABLE Singers ("
70+
+ "SingerId INT64 PRIMARY KEY, "
71+
+ "FirstName STRING(MAX), "
72+
+ "LastName STRING(MAX), "
73+
+ "Active BOOL)");
74+
statement.addBatch(
75+
"CREATE TABLE SingerHistory ("
76+
+ "SingerId INT64, "
77+
+ "Active BOOL, "
78+
+ "CreatedAt TIMESTAMP) "
79+
+ "PRIMARY KEY (SingerId, CreatedAt)");
80+
statement.executeBatch();
81+
}
82+
}
83+
}
84+
85+
@AfterClass
86+
public static void stopEmulator() {
87+
if (emulator != null) {
88+
emulator.stop();
89+
}
90+
}
91+
92+
@Test
93+
public void testIsolationLevel() throws SQLException {
94+
isolationLevel("emulator-project", "my-instance", "my-database", PROPERTIES);
95+
}
96+
97+
}

samples/spring-data-jdbc/googlesql/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<dependency>
3131
<groupId>com.google.cloud</groupId>
3232
<artifactId>google-cloud-spanner-bom</artifactId>
33-
<version>6.101.1</version>
33+
<version>6.102.0</version>
3434
<scope>import</scope>
3535
<type>pom</type>
3636
</dependency>

samples/spring-data-jdbc/postgresql/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<dependency>
3131
<groupId>com.google.cloud</groupId>
3232
<artifactId>google-cloud-spanner-bom</artifactId>
33-
<version>6.101.1</version>
33+
<version>6.102.0</version>
3434
<scope>import</scope>
3535
<type>pom</type>
3636
</dependency>
@@ -114,13 +114,13 @@
114114
<dependency>
115115
<groupId>net.bytebuddy</groupId>
116116
<artifactId>byte-buddy</artifactId>
117-
<version>1.17.7</version>
117+
<version>1.17.8</version>
118118
<scope>test</scope>
119119
</dependency>
120120
<dependency>
121121
<groupId>net.bytebuddy</groupId>
122122
<artifactId>byte-buddy-agent</artifactId>
123-
<version>1.17.7</version>
123+
<version>1.17.8</version>
124124
<scope>test</scope>
125125
</dependency>
126126
<dependency>

samples/spring-data-mybatis/googlesql/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<dependency>
3636
<groupId>com.google.cloud</groupId>
3737
<artifactId>google-cloud-spanner-bom</artifactId>
38-
<version>6.101.1</version>
38+
<version>6.102.0</version>
3939
<scope>import</scope>
4040
<type>pom</type>
4141
</dependency>
@@ -94,7 +94,7 @@
9494
<dependency>
9595
<groupId>com.google.cloud</groupId>
9696
<artifactId>google-cloud-spanner</artifactId>
97-
<version>6.101.1</version>
97+
<version>6.102.0</version>
9898
<type>test-jar</type>
9999
<scope>test</scope>
100100
</dependency>
@@ -108,13 +108,13 @@
108108
<dependency>
109109
<groupId>net.bytebuddy</groupId>
110110
<artifactId>byte-buddy</artifactId>
111-
<version>1.17.7</version>
111+
<version>1.17.8</version>
112112
<scope>test</scope>
113113
</dependency>
114114
<dependency>
115115
<groupId>net.bytebuddy</groupId>
116116
<artifactId>byte-buddy-agent</artifactId>
117-
<version>1.17.7</version>
117+
<version>1.17.8</version>
118118
<scope>test</scope>
119119
</dependency>
120120
<dependency>

0 commit comments

Comments
 (0)