Skip to content

Commit

Permalink
Lesson 4: Working with Data
Browse files Browse the repository at this point in the history
  • Loading branch information
philwebb committed Sep 24, 2016
1 parent 7bfe30c commit 2db53a6
Show file tree
Hide file tree
Showing 47 changed files with 1,156 additions and 0 deletions.
13 changes: 13 additions & 0 deletions livelessons-data/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
:compat-mode:
= Lesson 4: Working With Data

_How to design microservices that store and consume data in traditional
relational databases and newer NoSQL stores._

- link:livelessons-data-jpa[Relational Database with JPA]
- link:livelessons-data-jdbc[Relational Database with JDBC]
- link:livelessons-data-flyway[Flyway Migration]
- link:livelessons-data-redis[Redis]
- link:livelessons-data-mongodb[MongoDB]
- link:livelessons-data-elasticsearch[Elasticsearch]
- link:livelessons-data-rest[Spring Data REST]
1 change: 1 addition & 0 deletions livelessons-data/livelessons-data-elasticsearch/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
26 changes: 26 additions & 0 deletions livelessons-data/livelessons-data-elasticsearch/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
:compat-mode:
= Lesson 4: Working With Data (Elasticsearch)

== Introduction
This example shows how you can connect your microservce to Elasticsearch.

== Building and running the sample
Use the following commands to build run the application:

```
$ mvn clean package
$ java -jar target/livelessons-data-elasticsearch-1.0.0-SNAPSHOT.jar
```

The example uses an embedded elasticsearch server to store data. If you want to talk
to a real server you can set `spring.data.elasticsearch.cluster-name` and
`spring.data.elasticsearch.cluster-nodes` properties.

== Understanding the code
The familiar Car domain is used again in this example. This time `Car` is a elasticsearch
document (signified with the Spring Data `@Document` annotation). The same `Repository`
logic is used as before providing a `findByMakeIgnoringCase` method.

The `DataElasticsearchApplication` class also shows how you can use the
`ElasticsearchTemplate` to make native elasticsearch queries. In this case we are
performing a fuzzy search for manufacturers like `ronda`.
20 changes: 20 additions & 0 deletions livelessons-data/livelessons-data-elasticsearch/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>livelessons</groupId>
<artifactId>livelessons-data</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>livelessons-data-elasticsearch</artifactId>
<properties>
<main.basedir>../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package demo;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

@Document(indexName = "car", type = "car", shards = 1, replicas = 0, refreshInterval = "-1")
public class Car {

@Id
private Long id;

private String make;

private String model;

private int year;

Car() {
}

public Car(String make, String model, int year) {
super();
this.make = make;
this.model = model;
this.year = year;
}

public String getMake() {
return make;
}

public String getModel() {
return model;
}

public int getYear() {
return year;
}

@Override
public String toString() {
return make + " " + model + " " + year;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package demo;

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface CarRepository extends ElasticsearchRepository<Car, Long> {

Iterable<Car> findByMakeIgnoringCase(String make);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package demo;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;

import static org.elasticsearch.index.query.QueryBuilders.fuzzyLikeThisFieldQuery;

@SpringBootApplication
public class DataElasticsearchApplication {

@Bean
public InitializingBean seedDatabase(CarRepository repository) {
return () -> {
repository.deleteAll();
repository.save(new Car("Honda", "Civic", 1997));
repository.save(new Car("Honda", "Accord", 2003));
repository.save(new Car("Ford", "Escort", 1985));
};
}

@Bean
public CommandLineRunner example(CarRepository repository,
ElasticsearchTemplate template) {
return (args) -> {
System.err.println("From the repository...");
repository.findByMakeIgnoringCase("fOrD").forEach(System.err::println);

System.err.println("\nFrom the template...");
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(fuzzyLikeThisFieldQuery("make").likeText("Ronda")).build();
template.queryForList(query, Car.class).forEach(System.err::println);
};
}

public static void main(String[] args) {
SpringApplication.run(DataElasticsearchApplication.class, args);
System.exit(0);
}

}
22 changes: 22 additions & 0 deletions livelessons-data/livelessons-data-flyway/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
:compat-mode:
= Lesson 4: Working With Data (Flyway Migration)

== Introduction
This example shows how you can use flyway to upgrade a live database.

== Building and running the sample
Use the following commands to build run the application:

```
$ mvn clean package
$ java -jar target/livelessons-flyway-1.0.0-SNAPSHOT.jar
```

== Understanding the code
Building on the earlier JPA example this demo shows how a new `color` column could be
added to the database. The additional `flyway` dependency in the `pom.xml` along with
scripts in `src/main/db/migration` is all that's needed.

Two scripts are provided. The first creates the initial structure and the second upgrades
it. Flyway adds an additional meta-table that tracks when an update has been applied and
prevents it from running multiple times.
28 changes: 28 additions & 0 deletions livelessons-data/livelessons-data-flyway/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>livelessons</groupId>
<artifactId>livelessons-data</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>livelessons-data-flyway</artifactId>
<properties>
<main.basedir>../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Car {

@Id
@GeneratedValue
private long id;

private String make;

private String model;

private int year;

private String color;

Car() {
}

public Car(String make, String model, int year, String color) {
super();
this.make = make;
this.model = model;
this.year = year;
this.color = color;
}

public String getMake() {
return make;
}

public String getModel() {
return model;
}

public int getYear() {
return year;
}

public String getColor() {
return color;
}

@Override
public String toString() {
return make + " " + model + " " + year + " " + this.color;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package demo;

import org.springframework.data.repository.CrudRepository;

public interface CarRepository extends CrudRepository<Car, Long> {

Iterable<Car> findByMakeIgnoringCase(String make);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DataFlywayApplication {

@Bean
public CommandLineRunner exampleQuery(CarRepository repository) {
return args -> repository.findByMakeIgnoringCase("HONDA")
.forEach(System.err::println);
}

public static void main(String[] args) {
SpringApplication.run(DataFlywayApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
spring.jpa.hibernate.ddl-auto=validate
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE car (
id bigint NOT NULL,
make varchar(100),
model varchar(100),
year int,
PRIMARY KEY (id)
);

INSERT INTO car VALUES (0, 'Honda', 'Civic', 1997);
INSERT INTO car VALUES (1, 'Honda', 'Accord', 2003);
INSERT INTO car VALUES (2, 'Ford', 'Escort', 1985);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE car ADD COLUMN (color varchar(200));

UPDATE car SET COLOR = 'Red' WHERE color is null;
24 changes: 24 additions & 0 deletions livelessons-data/livelessons-data-jdbc/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
:compat-mode:
= Lesson 4: Working With Data (Relational Database with JDBC)

== Introduction
This example shows how you can access a classic relational database using Spring JDBC.

== Building and running the sample
Use the following commands to build run the application:

```
$ mvn clean package
$ java -jar target/livelessons-data-jdbc-1.0.0-SNAPSHOT.jar
```

== Understanding the code
This demo provides the same domain as the JPA sample but this time the `Car` class is
a POJO and isn't managed by JPA. The `CarRepository` implements the access logic and
maps returned rows to the actual object.

This sample also uses `src/main/resources/schema.sql` and `src/main/resources/data.sql`
scripts (picked up by convention) to create and populate the database.

If you want to try the application with a real MySQL server rather than an in-memory
database you can uncomment the entries in `src/main/resources/application.properties`.
29 changes: 29 additions & 0 deletions livelessons-data/livelessons-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>livelessons</groupId>
<artifactId>livelessons-data</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>livelessons-data-jdbc</artifactId>
<properties>
<main.basedir>../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Loading

0 comments on commit 2db53a6

Please sign in to comment.