Skip to content

Commit 2db53a6

Browse files
committed
Lesson 4: Working with Data
1 parent 7bfe30c commit 2db53a6

Some content is hidden

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

47 files changed

+1156
-0
lines changed

livelessons-data/README.adoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
:compat-mode:
2+
= Lesson 4: Working With Data
3+
4+
_How to design microservices that store and consume data in traditional
5+
relational databases and newer NoSQL stores._
6+
7+
- link:livelessons-data-jpa[Relational Database with JPA]
8+
- link:livelessons-data-jdbc[Relational Database with JDBC]
9+
- link:livelessons-data-flyway[Flyway Migration]
10+
- link:livelessons-data-redis[Redis]
11+
- link:livelessons-data-mongodb[MongoDB]
12+
- link:livelessons-data-elasticsearch[Elasticsearch]
13+
- link:livelessons-data-rest[Spring Data REST]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
data
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
:compat-mode:
2+
= Lesson 4: Working With Data (Elasticsearch)
3+
4+
== Introduction
5+
This example shows how you can connect your microservce to Elasticsearch.
6+
7+
== Building and running the sample
8+
Use the following commands to build run the application:
9+
10+
```
11+
$ mvn clean package
12+
$ java -jar target/livelessons-data-elasticsearch-1.0.0-SNAPSHOT.jar
13+
```
14+
15+
The example uses an embedded elasticsearch server to store data. If you want to talk
16+
to a real server you can set `spring.data.elasticsearch.cluster-name` and
17+
`spring.data.elasticsearch.cluster-nodes` properties.
18+
19+
== Understanding the code
20+
The familiar Car domain is used again in this example. This time `Car` is a elasticsearch
21+
document (signified with the Spring Data `@Document` annotation). The same `Repository`
22+
logic is used as before providing a `findByMakeIgnoringCase` method.
23+
24+
The `DataElasticsearchApplication` class also shows how you can use the
25+
`ElasticsearchTemplate` to make native elasticsearch queries. In this case we are
26+
performing a fuzzy search for manufacturers like `ronda`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-data</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-data-elasticsearch</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
18+
</dependency>
19+
</dependencies>
20+
</project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package demo;
2+
3+
import org.springframework.data.annotation.Id;
4+
import org.springframework.data.elasticsearch.annotations.Document;
5+
6+
@Document(indexName = "car", type = "car", shards = 1, replicas = 0, refreshInterval = "-1")
7+
public class Car {
8+
9+
@Id
10+
private Long id;
11+
12+
private String make;
13+
14+
private String model;
15+
16+
private int year;
17+
18+
Car() {
19+
}
20+
21+
public Car(String make, String model, int year) {
22+
super();
23+
this.make = make;
24+
this.model = model;
25+
this.year = year;
26+
}
27+
28+
public String getMake() {
29+
return make;
30+
}
31+
32+
public String getModel() {
33+
return model;
34+
}
35+
36+
public int getYear() {
37+
return year;
38+
}
39+
40+
@Override
41+
public String toString() {
42+
return make + " " + model + " " + year;
43+
}
44+
45+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package demo;
2+
3+
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
4+
5+
public interface CarRepository extends ElasticsearchRepository<Car, Long> {
6+
7+
Iterable<Car> findByMakeIgnoringCase(String make);
8+
9+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package demo;
2+
3+
import org.springframework.beans.factory.InitializingBean;
4+
import org.springframework.boot.CommandLineRunner;
5+
import org.springframework.boot.SpringApplication;
6+
import org.springframework.boot.autoconfigure.SpringBootApplication;
7+
import org.springframework.context.annotation.Bean;
8+
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
9+
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
10+
import org.springframework.data.elasticsearch.core.query.SearchQuery;
11+
12+
import static org.elasticsearch.index.query.QueryBuilders.fuzzyLikeThisFieldQuery;
13+
14+
@SpringBootApplication
15+
public class DataElasticsearchApplication {
16+
17+
@Bean
18+
public InitializingBean seedDatabase(CarRepository repository) {
19+
return () -> {
20+
repository.deleteAll();
21+
repository.save(new Car("Honda", "Civic", 1997));
22+
repository.save(new Car("Honda", "Accord", 2003));
23+
repository.save(new Car("Ford", "Escort", 1985));
24+
};
25+
}
26+
27+
@Bean
28+
public CommandLineRunner example(CarRepository repository,
29+
ElasticsearchTemplate template) {
30+
return (args) -> {
31+
System.err.println("From the repository...");
32+
repository.findByMakeIgnoringCase("fOrD").forEach(System.err::println);
33+
34+
System.err.println("\nFrom the template...");
35+
SearchQuery query = new NativeSearchQueryBuilder()
36+
.withQuery(fuzzyLikeThisFieldQuery("make").likeText("Ronda")).build();
37+
template.queryForList(query, Car.class).forEach(System.err::println);
38+
};
39+
}
40+
41+
public static void main(String[] args) {
42+
SpringApplication.run(DataElasticsearchApplication.class, args);
43+
System.exit(0);
44+
}
45+
46+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
:compat-mode:
2+
= Lesson 4: Working With Data (Flyway Migration)
3+
4+
== Introduction
5+
This example shows how you can use flyway to upgrade a live database.
6+
7+
== Building and running the sample
8+
Use the following commands to build run the application:
9+
10+
```
11+
$ mvn clean package
12+
$ java -jar target/livelessons-flyway-1.0.0-SNAPSHOT.jar
13+
```
14+
15+
== Understanding the code
16+
Building on the earlier JPA example this demo shows how a new `color` column could be
17+
added to the database. The additional `flyway` dependency in the `pom.xml` along with
18+
scripts in `src/main/db/migration` is all that's needed.
19+
20+
Two scripts are provided. The first creates the initial structure and the second upgrades
21+
it. Flyway adds an additional meta-table that tracks when an update has been applied and
22+
prevents it from running multiple times.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-data</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-data-flyway</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-data-jpa</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.flywaydb</groupId>
21+
<artifactId>flyway-core</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>com.h2database</groupId>
25+
<artifactId>h2</artifactId>
26+
</dependency>
27+
</dependencies>
28+
</project>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package demo;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.GeneratedValue;
5+
import javax.persistence.Id;
6+
7+
@Entity
8+
public class Car {
9+
10+
@Id
11+
@GeneratedValue
12+
private long id;
13+
14+
private String make;
15+
16+
private String model;
17+
18+
private int year;
19+
20+
private String color;
21+
22+
Car() {
23+
}
24+
25+
public Car(String make, String model, int year, String color) {
26+
super();
27+
this.make = make;
28+
this.model = model;
29+
this.year = year;
30+
this.color = color;
31+
}
32+
33+
public String getMake() {
34+
return make;
35+
}
36+
37+
public String getModel() {
38+
return model;
39+
}
40+
41+
public int getYear() {
42+
return year;
43+
}
44+
45+
public String getColor() {
46+
return color;
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return make + " " + model + " " + year + " " + this.color;
52+
}
53+
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package demo;
2+
3+
import org.springframework.data.repository.CrudRepository;
4+
5+
public interface CarRepository extends CrudRepository<Car, Long> {
6+
7+
Iterable<Car> findByMakeIgnoringCase(String make);
8+
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package demo;
2+
3+
import org.springframework.boot.CommandLineRunner;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
import org.springframework.context.annotation.Bean;
7+
8+
@SpringBootApplication
9+
public class DataFlywayApplication {
10+
11+
@Bean
12+
public CommandLineRunner exampleQuery(CarRepository repository) {
13+
return args -> repository.findByMakeIgnoringCase("HONDA")
14+
.forEach(System.err::println);
15+
}
16+
17+
public static void main(String[] args) {
18+
SpringApplication.run(DataFlywayApplication.class, args);
19+
}
20+
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
spring.jpa.hibernate.ddl-auto=validate
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CREATE TABLE car (
2+
id bigint NOT NULL,
3+
make varchar(100),
4+
model varchar(100),
5+
year int,
6+
PRIMARY KEY (id)
7+
);
8+
9+
INSERT INTO car VALUES (0, 'Honda', 'Civic', 1997);
10+
INSERT INTO car VALUES (1, 'Honda', 'Accord', 2003);
11+
INSERT INTO car VALUES (2, 'Ford', 'Escort', 1985);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ALTER TABLE car ADD COLUMN (color varchar(200));
2+
3+
UPDATE car SET COLOR = 'Red' WHERE color is null;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
:compat-mode:
2+
= Lesson 4: Working With Data (Relational Database with JDBC)
3+
4+
== Introduction
5+
This example shows how you can access a classic relational database using Spring JDBC.
6+
7+
== Building and running the sample
8+
Use the following commands to build run the application:
9+
10+
```
11+
$ mvn clean package
12+
$ java -jar target/livelessons-data-jdbc-1.0.0-SNAPSHOT.jar
13+
```
14+
15+
== Understanding the code
16+
This demo provides the same domain as the JPA sample but this time the `Car` class is
17+
a POJO and isn't managed by JPA. The `CarRepository` implements the access logic and
18+
maps returned rows to the actual object.
19+
20+
This sample also uses `src/main/resources/schema.sql` and `src/main/resources/data.sql`
21+
scripts (picked up by convention) to create and populate the database.
22+
23+
If you want to try the application with a real MySQL server rather than an in-memory
24+
database you can uncomment the entries in `src/main/resources/application.properties`.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-data</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-data-jdbc</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-jdbc</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>com.h2database</groupId>
21+
<artifactId>h2</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>mysql</groupId>
25+
<artifactId>mysql-connector-java</artifactId>
26+
<scope>runtime</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>

0 commit comments

Comments
 (0)