Skip to content

Commit 74dd46f

Browse files
ChengyuanZhaolesv
authored andcommitted
Spring data spanner sample (#1474)
* Spring Data Spanner Sample * readme * some pr comments * add bom * formatting * pom fix * pom typo * refactoring into a proper Spring Boot app * typo fix
1 parent 39aed7e commit 74dd46f

File tree

10 files changed

+503
-0
lines changed

10 files changed

+503
-0
lines changed

spanner/spring-data/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Spring Data Cloud Spanner Sample
2+
3+
An example that demonstrates read, write, and administrative operations
4+
using [Spring Data Cloud Spanner](https://github.com/spring-cloud/spring-cloud-gcp/blob/master/docs/src/main/asciidoc/spanner.adoc).
5+
6+
This sample requires [Java](https://www.java.com/en/download/) and [Maven](http://maven.apache.org/) for building the application.
7+
8+
This sample includes 3 classes that demonstrate how to use Spring Data Cloud Spanner to perform
9+
read, write, and database admin operations.
10+
11+
* `SpannerSchemaToolsSample` - create and drop interleaved tables based on a root Java entity class.
12+
* `SpannerTemplateSample` - perform read and write operations with Java entities.
13+
* `SpannerRepositorySample` - perform operations and queries by defining their operations in an interface.
14+
15+
16+
## Build and Run
17+
18+
1. **Follow the set-up instructions in [the documentation](https://cloud.google.com/java/docs/setup).**
19+
20+
2. Enable APIs for your project.
21+
[Click here](https://console.cloud.google.com/flows/enableapi?apiid=spanner.googleapis.com&showconfirmation=true)
22+
to visit Cloud Platform Console and enable the Google Cloud Spanner API.
23+
24+
3. Create a Cloud Spanner instance and database via the Cloud Plaform Console's
25+
[Cloud Spanner section](http://console.cloud.google.com/spanner).
26+
27+
4. Enable application default credentials by running the command `gcloud auth application-default login`.
28+
29+
5. Supply your instance and database name in `src/main/resources/application.properties`
30+
31+
6. Run the following Maven command to run `QuickStartSample`, which runs table creation, write, and read operations:
32+
```
33+
mvn clean spring-boot:run
34+
```

spanner/spring-data/pom.xml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!--
2+
Copyright 2019 Google Inc.
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+
<project>
17+
<modelVersion>4.0.0</modelVersion>
18+
19+
<properties>
20+
<maven.compiler.target>1.8</maven.compiler.target>
21+
<maven.compiler.source>1.8</maven.compiler.source>
22+
</properties>
23+
24+
<!--
25+
The parent pom defines common style checks and testing strategies for our samples.
26+
Removing or replacing it should not affect the execution of the samples in anyway.
27+
-->
28+
<parent>
29+
<groupId>com.google.cloud.samples</groupId>
30+
<artifactId>shared-configuration</artifactId>
31+
<version>1.0.11</version>
32+
</parent>
33+
34+
<groupId>com.example.spanner</groupId>
35+
<artifactId>spring-data</artifactId>
36+
<name>Spring Data Spanner Code Sample</name>
37+
38+
<dependencyManagement>
39+
<dependencies>
40+
<dependency>
41+
<groupId>org.springframework.cloud</groupId>
42+
<artifactId>spring-cloud-gcp-dependencies</artifactId>
43+
<version>1.1.2.RELEASE</version>
44+
<type>pom</type>
45+
<scope>import</scope>
46+
</dependency>
47+
</dependencies>
48+
</dependencyManagement>
49+
50+
<dependencies>
51+
<dependency>
52+
<groupId>org.springframework.cloud</groupId>
53+
<artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
54+
</dependency>
55+
</dependencies>
56+
57+
<build>
58+
<plugins>
59+
<plugin>
60+
<groupId>org.springframework.boot</groupId>
61+
<artifactId>spring-boot-maven-plugin</artifactId>
62+
<version>2.1.6.RELEASE</version>
63+
<configuration>
64+
<mainClass>com.example.spanner.QuickStartSample</mainClass>
65+
</configuration>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
</project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2019 Google Inc.
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;
18+
19+
//[START spring_data_spanner_album]
20+
import java.util.List;
21+
import org.springframework.cloud.gcp.data.spanner.core.mapping.NotMapped;
22+
import org.springframework.cloud.gcp.data.spanner.core.mapping.PrimaryKey;
23+
import org.springframework.cloud.gcp.data.spanner.core.mapping.Table;
24+
25+
/**
26+
* An entity class representing an Album.
27+
*/
28+
@Table(name = "Albums")
29+
public class Album {
30+
31+
@PrimaryKey
32+
long singerId;
33+
34+
@PrimaryKey(keyOrder = 2)
35+
long albumId;
36+
37+
String albumTitle;
38+
39+
long marketingBudget;
40+
41+
@NotMapped
42+
List<Album> relatedAlbums;
43+
44+
public Album(long singerId, long albumId, String albumTitle, long marketingBudget) {
45+
this.singerId = singerId;
46+
this.albumId = albumId;
47+
this.albumTitle = albumTitle;
48+
this.marketingBudget = marketingBudget;
49+
}
50+
}
51+
//[END spring_data_spanner_album]
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2019 Google Inc.
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;
18+
19+
import java.util.Arrays;
20+
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.boot.CommandLineRunner;
25+
import org.springframework.boot.SpringApplication;
26+
27+
/**
28+
* A quick-start sample that uses Spring Data Cloud Spanner to perform read, write, and DDL
29+
* operations.
30+
*/
31+
@org.springframework.boot.autoconfigure.SpringBootApplication
32+
public class QuickStartSample implements CommandLineRunner {
33+
34+
private static Logger LOG = LoggerFactory.getLogger(QuickStartSample.class);
35+
36+
@Autowired
37+
SpannerSchemaToolsSample spannerSchemaToolsSample;
38+
39+
@Autowired
40+
SpannerTemplateSample spannerTemplateSample;
41+
42+
@Autowired
43+
SpannerRepositorySample spannerRepositorySample;
44+
45+
public static void main(String[] args) {
46+
LOG.info("Starting Spring Data Cloud Spanner Sample.");
47+
SpringApplication.run(QuickStartSample.class, args);
48+
LOG.info("Spring Data Cloud Spanner Sample finished running.");
49+
}
50+
51+
public void run(String... args) {
52+
/*
53+
This call creates both the Singer and Album tables with an interleaved relationship.
54+
*/
55+
LOG.info("(SpannerSchemaToolsSample): Creating database tables if they don't exist.");
56+
spannerSchemaToolsSample.createTableIfNotExists();
57+
58+
Singer singer = new Singer();
59+
singer.singerId = 1L;
60+
singer.firstName = "John";
61+
singer.lastName = "Doe";
62+
singer.albums = Arrays.asList(new Album(1L, 10L, "album1", 11L),
63+
new Album(1L, 20L, "album2", 12L));
64+
65+
/*
66+
This call inserts the singer and performs a read query using a SpannerTemplate instance.
67+
*/
68+
LOG.info("(SpannerTemplateSample): Saving one singer.");
69+
spannerTemplateSample.runTemplateExample(singer);
70+
71+
/*
72+
This call uses queries defined in SingerRepository. The implementations of those queries
73+
are generated by Spring Data Cloud Spanner.
74+
*/
75+
LOG.info("(SpannerRepositorySample): Running queries.");
76+
spannerRepositorySample.runRepositoryExample();
77+
78+
/*
79+
This call drops both the sample Singer and Album tables.
80+
*/
81+
LOG.info("(SpannerSchemaToolsSample): Dropping Singer and Album tables.");
82+
spannerSchemaToolsSample.dropTables();
83+
84+
}
85+
86+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2019 Google Inc.
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;
18+
19+
//[START spring_data_spanner_singer]
20+
import java.util.Date;
21+
import java.util.List;
22+
import org.springframework.cloud.gcp.data.spanner.core.mapping.Embedded;
23+
import org.springframework.cloud.gcp.data.spanner.core.mapping.Interleaved;
24+
import org.springframework.cloud.gcp.data.spanner.core.mapping.PrimaryKey;
25+
import org.springframework.cloud.gcp.data.spanner.core.mapping.Table;
26+
27+
/**
28+
* An entity and table holding singers.
29+
*/
30+
@Table(name = "Singers")
31+
public class Singer {
32+
@PrimaryKey
33+
long singerId;
34+
35+
String firstName;
36+
37+
String lastName;
38+
39+
Date birthDate;
40+
41+
@Interleaved
42+
List<Album> albums;
43+
}
44+
//[END spring_data_spanner_singer]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2019 Google Inc.
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;
18+
19+
//[START spring_data_spanner_singer_repository]
20+
import com.google.cloud.spanner.Key;
21+
import java.util.List;
22+
import org.springframework.cloud.gcp.data.spanner.repository.SpannerRepository;
23+
import org.springframework.cloud.gcp.data.spanner.repository.query.Query;
24+
import org.springframework.data.repository.query.Param;
25+
26+
/**
27+
* An interface of various Query Methods. The behavior of the queries is defined only by
28+
* their names, arguments, or annotated SQL strings. The implementation of these functions
29+
* is generated by Spring Data Cloud Spanner.
30+
*/
31+
public interface SingerRepository extends SpannerRepository<Singer, Key> {
32+
List<Singer> findByLastName(String lastName);
33+
34+
int countByFirstName(String firstName);
35+
36+
int deleteByLastName(String lastName);
37+
38+
List<Singer> findTop3DistinctByFirstNameAndSingerIdIgnoreCaseOrLastNameOrderByLastNameDesc(
39+
String firstName, String lastName, long singerId);
40+
41+
@Query("SELECT * FROM Singers WHERE firstName LIKE '%@fragment';")
42+
List<Singer> getByQuery(@Param("fragment") String firstNameFragment);
43+
}
44+
//[END spring_data_spanner_singer_repository]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2019 Google Inc.
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;
18+
19+
// [START spring_data_spanner_repository_sample]
20+
import java.util.List;
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.stereotype.Component;
23+
24+
/**
25+
* A quick start code for Spring Data Cloud Spanner.
26+
* It demonstrates how to use a SpannerRepository to execute read-write queries
27+
* generated from interface definitions.
28+
*
29+
*/
30+
@Component
31+
public class SpannerRepositorySample {
32+
33+
@Autowired
34+
SingerRepository singerRepository;
35+
36+
public void runRepositoryExample() {
37+
List<Singer> lastNameSingers = this.singerRepository.findByLastName("a last name");
38+
39+
int fistNameCount = this.singerRepository.countByFirstName("a first name");
40+
41+
int deletedLastNameCount = this.singerRepository.deleteByLastName("a last name");
42+
}
43+
44+
}
45+
// [END spring_data_spanner_repository_sample]

0 commit comments

Comments
 (0)