dzone java 8 block buster: query databases using streams

61
Meetup Gothenburg Dec 28 2015 Per-Åke Minborg [email protected]

Upload: speedment-inc

Post on 25-Jan-2017

399 views

Category:

Software


1 download

TRANSCRIPT

Page 1: DZone Java 8 Block Buster: Query Databases Using Streams

Meetup Gothenburg Dec 28 2015 Per-Åke [email protected]

Page 2: DZone Java 8 Block Buster: Query Databases Using Streams

Palo Alto Office Speedment Java One Presentation

Page 3: DZone Java 8 Block Buster: Query Databases Using Streams

Background

Page 4: DZone Java 8 Block Buster: Query Databases Using Streams

Before Speedment

Connector

JDBC

ORM

JPA

ApplicationPROSWidely spread standard

• Many providers• Many developers

You can work with a relational database as if it were object oriented Increased productivity Provides a certain degree of abstraction (you can replace your DBMS)

CONS Slows down the application and gives unpredictable performance You can not access all Java 8 featuresTime consuming to write applications for existing databases, You must still write SQL, HQL, et. AlHigher the risk for errors

Java

Page 5: DZone Java 8 Block Buster: Query Databases Using Streams

ORM

JPA

Speedment- a Java Development Tool

Connector

JDBC

Application Object Oriented functional programming

Fast to develop Fast Execution Easy to test Secure

Make use of all Java 8 features Domain Model reflects your existing

datasource Automatic generation of Code (”error free”)

Java

Speedment

Java 8

Application

Page 6: DZone Java 8 Block Buster: Query Databases Using Streams

Speedment- a Java Development Tool

Page 7: DZone Java 8 Block Buster: Query Databases Using Streams

Code Examples• Embrace Java 8 paradigms with stream(), filter(), sort(), limit() etc.

• Forget about SQL, JQL et. al

Page 8: DZone Java 8 Block Buster: Query Databases Using Streams

Database Table “hare”

mysql> explain hare;+-------+-------------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+----------------+| id | int(11) | NO | PRI | NULL | auto_increment || name | varchar(45) | NO | | NULL | || color | varchar(45) | NO | | NULL | || age | int(11) | NO | | NU | |+-------+-------------+------+-----+---------+----------------+4 rows in set (0.01 sec)

Page 9: DZone Java 8 Block Buster: Query Databases Using Streams

Code Generationpublic interface Hare extends Entity<Hare> {

public final static ReferenceComparableField<Hare, Integer> ID = … public final static ReferenceComparableStringField<Hare> NAME = … public final static ReferenceComparableStringField<Hare> COLOR = … public final static ReferenceComparableField<Hare, Integer> AGE = …

Integer getId(); String getName(); String getColor(); Integer getAge();

Hare setId(Integer id); Hare setName(String name); Hare setColor(String color); Hare setAge(Integer age);

/** Graph-like traversal methods eliminating JOINs */ Stream<Carrot> findCarrotsByOwner(); Stream<Carrot> findCarrotsByRival(); Stream<Carrot> findCarrots();}

Page 10: DZone Java 8 Block Buster: Query Databases Using Streams
Page 11: DZone Java 8 Block Buster: Query Databases Using Streams

Querying using Java 8 StreamsList<Hare> oldHares = hares.stream() .filter(Hare.AGE.greaterThan(4)) .collect(toList());

SELECT * from `hare`WHERE`age` > 4;

Page 12: DZone Java 8 Block Buster: Query Databases Using Streams

Stream Fundamentals Detailed description Slide 35-45

Page 13: DZone Java 8 Block Buster: Query Databases Using Streams

Depends on Terminating OperationOptional<Hare> oldHare = hares.stream() .filter(Hare.AGE.greaterThan(4)) .findAny();

SELECT * from `hare`WHERE`age` > 4 LIMIT 1;

Page 14: DZone Java 8 Block Buster: Query Databases Using Streams

Depends on Terminating Operationlong noOldHares = hares.stream() .filter(Hare.AGE.greaterThan(4)) .count();

SELECT count(*) from `hare`WHERE`age` > 4;

Page 15: DZone Java 8 Block Buster: Query Databases Using Streams

Entities are linked

Optional<Carrot> carrot = hares.stream() .filter(Hare.NAME.equal(”Spire”)) // Carrot is a foreign key. .flatmap(Hare::findCarrots) .findAny();

Page 16: DZone Java 8 Block Buster: Query Databases Using Streams

Multi-threading

hares.stream() .parallel() .forEach(doExpensiveOperation());

Page 17: DZone Java 8 Block Buster: Query Databases Using Streams

PersistenceHare harry = hares.newInstance() .setName("Harry") .setColor("Gray") .setAge(3) .persist();

// OR JPA-style

entityManager.persist(harry);

Page 18: DZone Java 8 Block Buster: Query Databases Using Streams

Delete Using Streams users.stream()   .filter(User.ID.greaterThan(4))   .forEach(User::delete);

DELETE FROM `user`WHERE `id` > 4;

Page 19: DZone Java 8 Block Buster: Query Databases Using Streams

Initialization

Speedment speedment = new HareApplication().build();Manager<Hare> hares = speedment.managerOf(Hare.class);

Page 20: DZone Java 8 Block Buster: Query Databases Using Streams

Speedment Insane Mode•Extreme Performance, real time big Data

•Convert large databases into In-JVM-memory Java Objects

•Scales Linearly -More CPUs, More Insane

Page 21: DZone Java 8 Block Buster: Query Databases Using Streams

In Memory Initialization

Speedment speedment = new HareApplication()

.with(OnHeapReadOnlyCacheComponent.class) .build();

Page 22: DZone Java 8 Block Buster: Query Databases Using Streams
Page 23: DZone Java 8 Block Buster: Query Databases Using Streams

How does it Work?

23

1 In-JVM-memory cache2 Java Objects in Graph View3 Separates Reads and WritesReflection in

real time

ApplicationJVM

Read

Write

Page 24: DZone Java 8 Block Buster: Query Databases Using Streams

Why will in-JVM-Memory give Insane Speed?

Database In JVM Memory

Compare latencies using the Speed of Light

Page 25: DZone Java 8 Block Buster: Query Databases Using Streams

Why will in-JVM Memory give Insane Speed?• Keep everything in-JVM

• No need to check if an object is in cache

• We can organize objects knowing that we have them all

• We do not even have to look at individual objects -> O(1)

• Everything is Java

Size

Time

O(1)

O(n)

Page 26: DZone Java 8 Block Buster: Query Databases Using Streams

Speedment – OSS and Enterprise

Page 27: DZone Java 8 Block Buster: Query Databases Using Streams

Cloud Deployment

RDBMS

Speedment

Speedment

Speedment Speedment

Speedment

• Spin up nodes as you grow

• Partition data over nodes

Page 28: DZone Java 8 Block Buster: Query Databases Using Streams

How can I fit my full Database in JVM Memory?

~24 GB

>1 TB

>4 TB

On-HeapOff-Heap

SSD

SQL

Database Size(After Compression)

Page 29: DZone Java 8 Block Buster: Query Databases Using Streams

Scale out with our partner Hazelcast• Set up a cluster in the Cloud• Scale out your existing database• Set up Terabytes of RAM

Page 30: DZone Java 8 Block Buster: Query Databases Using Streams

Properties:• The API will remain the same regardless of selected Storage Engine

• Massively concurrent and lock free

• Scale with CPU performance and number of cores

• Eventually consistent

• Transaction safe, if you want

Page 31: DZone Java 8 Block Buster: Query Databases Using Streams

Configuration• Groovy script like Gradle

• Config file is placed at the same location as the POM

dbms { schema { table { name = ”hare"; column { name = "name"; } } }}

Page 32: DZone Java 8 Block Buster: Query Databases Using Streams

Ease of use:• Single Maven dependency in POM

• Maven targets

• Works with Gradle

• GUI to automatically derive the groovy config file from existing databases

Page 33: DZone Java 8 Block Buster: Query Databases Using Streams

Properties:• The database ”owns” the data

• Data is reflected into Materialized Object Views (MOVs)

• MOVs and application resides in the same JVM

• Most operations are O(1)

• persons.byName(“Bob") -> Map<PK,Person> with 1000 persons in 100 ns (30 m)

• TCP/IP RTT 100 us -> +1000 "finds" per TCP RT.

• In-memory DBs with zero query latency are snails by definition

Page 34: DZone Java 8 Block Buster: Query Databases Using Streams

http://localhost:4567/trades/1001/200? from=0&to=1441147840000&callback=Ext.data.JsonP.callback1

Ext.data.JsonP.callback1([{'start':1420131600000,'stop':1420236681000,'average':100876,'open':100000,'close':102209,'high':104060,'low':98714},{'start':1420236682000,'stop':1420243199000,'average':102339,'open':102224,'close':103348,'high':103366,'low':101603},{'start':1420477200000,'stop':1420502399000,'average':102272,'open':103353,'close':103316,'high':103608,'low':100819},{'start':1420563600000,'stop':1420657005000,'average':101682,'open':103315,'close':102292,'high':103755,'low':99241},

… (200 rows in total) ...{'start':1441147839000,'stop':1441147839000,'average':142165,'open':142165,'close':142165,'high':142165,'low':142165}]);

Objectives:

Page 35: DZone Java 8 Block Buster: Query Databases Using Streams

Stream Fundamentals Per-Åke [email protected]

Page 36: DZone Java 8 Block Buster: Query Databases Using Streams

Setup

36

DB App

Pwd ?

In-JVM Cache

Page 37: DZone Java 8 Block Buster: Query Databases Using Streams

Stream<Trade> stream = trades.stream();

37

DB

Data Source

Trade5 Trade4 Trade3 Trade2 Trade1

Page 38: DZone Java 8 Block Buster: Query Databases Using Streams

trades.stream().parallel();

38

TradeN

Trade4

Trade3

Trade2

Trade1

TradeX

Thread 1

Thread 2

Thread N

DB

Data Source

Page 39: DZone Java 8 Block Buster: Query Databases Using Streams

trades.stream().filter(Predicate<Trade> predicate);

39

Trade2 Trade1predicate.test(trade)Trade5 Trade4

Trade3

false

true

Page 40: DZone Java 8 Block Buster: Query Databases Using Streams

trades.stream().map(Function<Trade,String> mapper);

40

Json2 Json1Trade5 Trade4mapper.

apply(trade)

e.g. Trade::toJson

Page 41: DZone Java 8 Block Buster: Query Databases Using Streams

trades.stream().collect(Collector collector);

41

TradeN

Trade4

Trade3

Trade2

Trade1

TradeX

apply(trade)

apply(trade)

apply(trade)

Page 42: DZone Java 8 Block Buster: Query Databases Using Streams

Complete Stream

42

DB

Data Source

Page 43: DZone Java 8 Block Buster: Query Databases Using Streams

Finding first and last date/time in an interval

43

from to

selected

Page 44: DZone Java 8 Block Buster: Query Databases Using Streams

trades.stream().parallel().filter(DATE.between(from, to)).filter(STOCK.equal(stock)).mapToLong(Trade::getDate).summaryStatistics();

44

2 3 4

2 3 4

2 3 4

5

12345

DB

Data Source

Page 45: DZone Java 8 Block Buster: Query Databases Using Streams

45

DB

Data Source 1

4

4

4

52

3

trades.stream().parallel().filter(DATE.between(from, to)).filter(STOCK.equal(stock)).mapToLong(Trade::getDate).summaryStatistics();

12345

Page 46: DZone Java 8 Block Buster: Query Databases Using Streams

Generating a REST APIIntroduction to Speedment and Sencha

Emil [email protected]

Page 47: DZone Java 8 Block Buster: Query Databases Using Streams

Outline●The Speedment + Sencha Software Stack●Using the Pivotgrid Plugin for Speedment

Page 48: DZone Java 8 Block Buster: Query Databases Using Streams

Overview of the Software Stack

DB

Javascript Framework

ServerFramework

DB Abstraction Layer

HTML5RESTJava 8JDBC

Page 49: DZone Java 8 Block Buster: Query Databases Using Streams

Database Layer●Holds all the data collected from various sources●High Level of Normalization

Sale

ProductSalesperson

Customer

Country

Region

Office

Cost Price

Count

Page 50: DZone Java 8 Block Buster: Query Databases Using Streams

Database Abstraction Layer●Presents an Object-Oriented view of the database●Write expressive and powerful queries●Optimize reading by using in-memory caching●Better testability and higher productivity

speedment.managerOf(Sale.class) .stream() .filter(Sale.PRODUCT.equal(105)) .collect(toList());

Page 51: DZone Java 8 Block Buster: Query Databases Using Streams

Server Framework●A lightweight webserver●Separates client/server-responsabilitys●Execute selected business logic as response to REST commands●Low Level of Abstraction

http://localhost:8123/salesinfo/?c=callback&filter=[{...}]

Page 52: DZone Java 8 Block Buster: Query Databases Using Streams

Javascript Framework●Presents data in user-friendly components●User can navigate the data in the browser●Automatically requests additional data from the server

Page 53: DZone Java 8 Block Buster: Query Databases Using Streams

Introduction to the Pivot Grid for Speedment●Generate a full-fledged server application from your database●Select exactly which data to expose in the API●Define aliases for columns and tables●Map between different data types●Create virtual columns calculated in real-time

Page 54: DZone Java 8 Block Buster: Query Databases Using Streams

Step 1 – Create a New Project

Page 55: DZone Java 8 Block Buster: Query Databases Using Streams

Step 2 – Find Pivotgrid Archetype

Page 56: DZone Java 8 Block Buster: Query Databases Using Streams

Step 3 – Name Project

Page 57: DZone Java 8 Block Buster: Query Databases Using Streams

Step 4 – Run Speedment GUI

Page 58: DZone Java 8 Block Buster: Query Databases Using Streams

Step 5 – Press Generate

Page 59: DZone Java 8 Block Buster: Query Databases Using Streams

Step 6 – Run Application

Page 60: DZone Java 8 Block Buster: Query Databases Using Streams

Example Application: Salesinfo

Page 61: DZone Java 8 Block Buster: Query Databases Using Streams

Thanks!