Skip to content

Commit 3476106

Browse files
authored
docs: add sample for Spring Data JDBC with GoogleSQL (#2027)
1 parent 5d7b9de commit 3476106

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2214
-90
lines changed

.github/workflows/spring-data-jdbc-sample.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ jobs:
2525
with:
2626
distribution: temurin
2727
java-version: 17
28-
- name: Run tests
28+
- name: Run tests on GoogleSQL
2929
run: mvn test
30-
working-directory: samples/spring-data-jdbc
30+
working-directory: samples/spring-data-jdbc/googlesql
31+
- name: Run tests on PostgreSQL
32+
run: mvn test
33+
working-directory: samples/spring-data-jdbc/postgresql

samples/spring-data-jdbc/README.md

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,17 @@
1-
# Spring Data JDBC Sample Application with Cloud Spanner PostgreSQL
1+
# Spring Data JDBC
22

3-
This sample application shows how to develop portable applications using Spring Data JDBC in
4-
combination with Cloud Spanner PostgreSQL. This application can be configured to run on either a
5-
[Cloud Spanner PostgreSQL](https://cloud.google.com/spanner/docs/postgresql-interface) database or
6-
an open-source PostgreSQL database. The only change that is needed to switch between the two is
7-
changing the active Spring profile that is used by the application.
8-
9-
The application uses the Cloud Spanner JDBC driver to connect to Cloud Spanner PostgreSQL, and it
10-
uses the PostgreSQL JDBC driver to connect to open-source PostgreSQL. Spring Data JDBC works with
11-
both drivers and offers a single consistent API to the application developer, regardless of the
12-
actual database or JDBC driver being used.
13-
14-
This sample shows:
15-
16-
1. How to use Spring Data JDBC with Cloud Spanner PostgreSQL.
17-
2. How to develop a portable application that runs on both Google Cloud Spanner PostgreSQL and
18-
open-source PostgreSQL with the same code base.
19-
3. How to use bit-reversed sequences to automatically generate primary key values for entities.
20-
21-
__NOTE__: This application does __not require PGAdapter__. Instead, it connects to Cloud Spanner
22-
PostgreSQL using the Cloud Spanner JDBC driver.
23-
24-
## Cloud Spanner PostgreSQL
25-
26-
Cloud Spanner PostgreSQL provides language support by expressing Spanner database functionality
27-
through a subset of open-source PostgreSQL language constructs, with extensions added to support
28-
Spanner functionality like interleaved tables and hinting.
29-
30-
The PostgreSQL interface makes the capabilities of Spanner —__fully managed, unlimited scale, strong
31-
consistency, high performance, and up to 99.999% global availability__— accessible using the
32-
PostgreSQL dialect. Unlike other services that manage actual PostgreSQL database instances, Spanner
33-
uses PostgreSQL-compatible syntax to expose its existing scale-out capabilities. This provides
34-
familiarity for developers and portability for applications, but not 100% PostgreSQL compatibility.
35-
The SQL syntax that Spanner supports is semantically equivalent PostgreSQL, meaning schemas
36-
and queries written against the PostgreSQL interface can be easily ported to another PostgreSQL
37-
environment.
38-
39-
This sample showcases this portability with an application that works on both Cloud Spanner PostgreSQL
40-
and open-source PostgreSQL with the same code base.
41-
42-
## Spring Data JDBC
3+
This directory contains two sample applications for using Spring Data JDBC
4+
with the Spanner JDBC driver.
435

446
[Spring Data JDBC](https://spring.io/projects/spring-data-jdbc) is part of the larger Spring Data
45-
family. It makes it easy to implement JDBC based repositories. This module deals with enhanced
46-
support for JDBC based data access layers.
7+
family. It makes it easy to implement JDBC based repositories.
8+
This module deals with enhanced support for JDBC based data access layers.
479

4810
Spring Data JDBC aims at being conceptually easy. In order to achieve this it does NOT offer caching,
4911
lazy loading, write behind or many other features of JPA. This makes Spring Data JDBC a simple,
5012
limited, opinionated ORM.
5113

52-
## Sample Application
53-
54-
This sample shows how to create a portable application using Spring Data JDBC and the Cloud Spanner
55-
PostgreSQL dialect. The application works on both Cloud Spanner PostgreSQL and open-source
56-
PostgreSQL. You can switch between the two by changing the active Spring profile:
57-
* Profile `cs` runs the application on Cloud Spanner PostgreSQL.
58-
* Profile `pg` runs the application on open-source PostgreSQL.
59-
60-
The default profile is `cs`. You can change the default profile by modifying the
61-
[application.properties](src/main/resources/application.properties) file.
62-
63-
### Running the Application
64-
65-
1. Choose the database system that you want to use by choosing a profile. The default profile is
66-
`cs`, which runs the application on Cloud Spanner PostgreSQL. Modify the default profile in the
67-
[application.properties](src/main/resources/application.properties) file.
68-
2. Modify either [application-cs.properties](src/main/resources/application-cs.properties) or
69-
[application-pg.properties](src/main/resources/application-pg.properties) to point to an existing
70-
database. If you use Cloud Spanner, the database that the configuration file references must be a
71-
database that uses the PostgreSQL dialect.
72-
3. Run the application with `mvn spring-boot:run`.
73-
74-
### Main Application Components
75-
76-
The main application components are:
77-
* [DatabaseSeeder.java](src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java): This
78-
class is responsible for creating the database schema and inserting some initial test data. The
79-
schema is created from the [create_schema.sql](src/main/resources/create_schema.sql) file. The
80-
`DatabaseSeeder` class loads this file into memory and executes it on the active database using
81-
standard JDBC APIs. The class also removes Cloud Spanner-specific extensions to the PostgreSQL
82-
dialect when the application runs on open-source PostgreSQL.
83-
* [JdbcConfiguration.java](src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java):
84-
Spring Data JDBC by default detects the database dialect based on the JDBC driver that is used.
85-
This class overrides this default and instructs Spring Data JDBC to also use the PostgreSQL
86-
dialect for Cloud Spanner PostgreSQL.
87-
* [AbstractEntity.java](src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java):
88-
This is the shared base class for all entities in this sample application. It defines a number of
89-
standard attributes, such as the identifier (primary key). The primary key is automatically
90-
generated using a (bit-reversed) sequence. [Bit-reversed sequential values](https://cloud.google.com/spanner/docs/schema-design#bit_reverse_primary_key)
91-
are considered a good choice for primary keys on Cloud Spanner.
92-
* [Application.java](src/main/java/com/google/cloud/spanner/sample/Application.java): The starter
93-
class of the application. It contains a command-line runner that executes a selection of queries
94-
and updates on the database.
95-
14+
- [GoogleSQL](googlesql): This sample uses the Spanner GoogleSQL dialect.
15+
- [PostgreSQL](postgresql): This sample uses the Spanner PostgreSQL dialect and the Spanner JDBC
16+
driver. It does not use PGAdapter. The sample application can also be configured to run on open
17+
source PostgreSQL, and shows how a portable application be developed using this setup.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Spring Data JDBC Sample Application with Spanner GoogleSQL
2+
3+
This sample application shows how to use Spring Data JDBC with Spanner GoogleSQL.
4+
5+
This sample shows:
6+
7+
1. How to use Spring Data JDBC with Spanner GoogleSQL.
8+
2. How to use bit-reversed identity columns to automatically generate primary key values for entities.
9+
3. How to set the transaction isolation level that is used by the Spanner JDBC driver.
10+
11+
## Spring Data JDBC
12+
13+
[Spring Data JDBC](https://spring.io/projects/spring-data-jdbc) is part of the larger Spring Data
14+
family. It makes it easy to implement JDBC based repositories. This module deals with enhanced
15+
support for JDBC based data access layers.
16+
17+
Spring Data JDBC aims at being conceptually easy. In order to achieve this it does NOT offer caching,
18+
lazy loading, write behind or many other features of JPA. This makes Spring Data JDBC a simple,
19+
limited, opinionated ORM.
20+
21+
### Running the Application
22+
23+
The application by default runs on the Spanner Emulator.
24+
25+
1. Modify the [application.properties](src/main/resources/application.properties) to point to an existing
26+
database. The database must use the GoogleSQL dialect.
27+
2. Run the application with `mvn spring-boot:run`.
28+
29+
### Main Application Components
30+
31+
The main application components are:
32+
* [DatabaseSeeder.java](src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java): This
33+
class is responsible for creating the database schema and inserting some initial test data. The
34+
schema is created from the [create_schema.sql](src/main/resources/create_schema.sql) file. The
35+
`DatabaseSeeder` class loads this file into memory and executes it on the active database using
36+
standard JDBC APIs.
37+
* [SpannerDialectProvider](src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java):
38+
Spring Data JDBC by default detects the database dialect based on the JDBC driver that is used.
39+
Spanner GoogleSQL is not automatically recognized by Spring Data, so we add a dialect provider
40+
for Spanner.
41+
* [SpannerDialect](src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java):
42+
Spring Data JDBC requires a dialect for the database, so it knows which features are supported,
43+
and how to build clauses like `LIMIT` and `FOR UPDATE`. This class provides this information. It
44+
is based on the built-in `AnsiDialect` in Spring Data JDBC.
45+
* [JdbcConfiguration.java](src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java):
46+
This configuration file serves two purposes:
47+
1. Make sure `OpenTelemetry` is initialized before any data sources.
48+
2. Add a converter for `LocalDate` properties. Spring Data JDBC by default map these to `TIMESTAMP`
49+
columns, but a better fit in Spanner is `DATE`.
50+
* [AbstractEntity.java](src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java):
51+
This is the shared base class for all entities in this sample application. It defines a number of
52+
standard attributes, such as the identifier (primary key). The primary key is automatically
53+
generated using a (bit-reversed) sequence. [Bit-reversed sequential values](https://cloud.google.com/spanner/docs/schema-design#bit_reverse_primary_key)
54+
are considered a good choice for primary keys on Cloud Spanner.
55+
* [Application.java](src/main/java/com/google/cloud/spanner/sample/Application.java): The starter
56+
class of the application. It contains a command-line runner that executes a selection of queries
57+
and updates on the database.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.example</groupId>
8+
<artifactId>cloud-spanner-spring-data-jdbc-googlesql-example</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
<description>
11+
Sample application showing how to use Spring Data JDBC with Cloud Spanner GoogleSQL.
12+
</description>
13+
14+
<properties>
15+
<java.version>17</java.version>
16+
<maven.compiler.source>17</maven.compiler.source>
17+
<maven.compiler.target>17</maven.compiler.target>
18+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19+
</properties>
20+
21+
<dependencyManagement>
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.data</groupId>
25+
<artifactId>spring-data-bom</artifactId>
26+
<version>2024.1.5</version>
27+
<scope>import</scope>
28+
<type>pom</type>
29+
</dependency>
30+
<dependency>
31+
<groupId>com.google.cloud</groupId>
32+
<artifactId>google-cloud-spanner-bom</artifactId>
33+
<version>6.91.1</version>
34+
<scope>import</scope>
35+
<type>pom</type>
36+
</dependency>
37+
<dependency>
38+
<groupId>com.google.cloud</groupId>
39+
<artifactId>libraries-bom</artifactId>
40+
<version>26.59.0</version>
41+
<scope>import</scope>
42+
<type>pom</type>
43+
</dependency>
44+
<dependency>
45+
<groupId>io.opentelemetry</groupId>
46+
<artifactId>opentelemetry-bom</artifactId>
47+
<version>1.49.0</version>
48+
<type>pom</type>
49+
<scope>import</scope>
50+
</dependency>
51+
</dependencies>
52+
</dependencyManagement>
53+
54+
<dependencies>
55+
<dependency>
56+
<groupId>org.springframework.boot</groupId>
57+
<artifactId>spring-boot-starter-data-jdbc</artifactId>
58+
<version>3.4.5</version>
59+
</dependency>
60+
61+
<!-- Add the Spanner JDBC driver. -->
62+
<dependency>
63+
<groupId>com.google.cloud</groupId>
64+
<artifactId>google-cloud-spanner-jdbc</artifactId>
65+
<exclusions>
66+
<exclusion>
67+
<groupId>com.google.api.grpc</groupId>
68+
<artifactId>proto-google-cloud-spanner-executor-v1</artifactId>
69+
</exclusion>
70+
</exclusions>
71+
</dependency>
72+
73+
<!-- Add OpenTelemetry for tracing and metrics. -->
74+
<dependency>
75+
<groupId>io.opentelemetry</groupId>
76+
<artifactId>opentelemetry-sdk</artifactId>
77+
</dependency>
78+
<dependency>
79+
<groupId>com.google.cloud.opentelemetry</groupId>
80+
<artifactId>exporter-trace</artifactId>
81+
<version>0.34.0</version>
82+
</dependency>
83+
<dependency>
84+
<groupId>com.google.cloud.opentelemetry</groupId>
85+
<artifactId>exporter-metrics</artifactId>
86+
<version>0.34.0</version>
87+
</dependency>
88+
89+
<!-- Add testcontainers for running the Spanner emulator -->
90+
<dependency>
91+
<groupId>org.testcontainers</groupId>
92+
<artifactId>testcontainers</artifactId>
93+
<version>1.21.0</version>
94+
</dependency>
95+
96+
<dependency>
97+
<groupId>com.google.collections</groupId>
98+
<artifactId>google-collections</artifactId>
99+
<version>1.0</version>
100+
</dependency>
101+
102+
<!-- Test dependencies -->
103+
<dependency>
104+
<groupId>com.google.cloud</groupId>
105+
<artifactId>google-cloud-spanner</artifactId>
106+
<type>test-jar</type>
107+
<scope>test</scope>
108+
</dependency>
109+
<dependency>
110+
<groupId>com.google.api</groupId>
111+
<artifactId>gax-grpc</artifactId>
112+
<classifier>testlib</classifier>
113+
<scope>test</scope>
114+
</dependency>
115+
<dependency>
116+
<groupId>junit</groupId>
117+
<artifactId>junit</artifactId>
118+
<version>4.13.2</version>
119+
</dependency>
120+
</dependencies>
121+
122+
<build>
123+
<plugins>
124+
<plugin>
125+
<groupId>com.spotify.fmt</groupId>
126+
<artifactId>fmt-maven-plugin</artifactId>
127+
<version>2.25</version>
128+
<executions>
129+
<execution>
130+
<goals>
131+
<goal>format</goal>
132+
</goals>
133+
</execution>
134+
</executions>
135+
</plugin>
136+
</plugins>
137+
</build>
138+
</project>

0 commit comments

Comments
 (0)