JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4489]

Speedment, Inc.
Speedment, Inc.Speedment, Inc.
Tutorial: How to Generate Customized Java 8
Code from Your Database
Per Minborg
CTO, Speedment, Inc
Emil Forslund
Developer, Speedment, Inc.
Every Decision a Developer Makes is a
Trade-off
The best code is
no code at all
Using Code Generation
• Makes the code efficient
and short
• Modifications are done
once and applied
everywhere
• Minimizes errors
• “DRY” (Don’t Repeat
Yourself) vs. ”WET” (We
Enjoy Typing)
• “Code your code”
But how can we control the generated code?
About Us
Per Minborg
• Founder of several IT companies
• Lives in Palo Alto
• 20 years of Java experience
• 15+ US patents
• Speaker at Java events
• Blog: Minborg’s Java Pot
Emil Forslund
• Java Developer
• Lives in Palo Alto
• 8 years of Java
experience
• Speaker at Java events
• Blog: Age of Java
Spire
• Speedment Open Source mascot
• Lives on GitHub
• 1.5 years of mascot experience
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Do You Recognize This Code?
Class.forName("org.postgresql.Driver");
try (final Connection conn = DriverManager.getConnection(
"jdbc:postgresql://hostname:port/dbname",
"username",
"password")) {
// Database Logic Here...
}
Why Creating DB-Apps is So Time
Consuming
• Even trivial database operations require a
lot of boilerplate code
• Mixing SQL and Java is error-prone
• ORMs require you to write annotated
POJOs for every table
• Creating even a simple DB app can take
hours
Open-Source Project Speedment
• Stream ORM Java toolkit and
runtime
• Generate domain-model from the
database
• No need for complicated
configurations or setup
• All operations are type-safe
• Data is accessed using Java 8
Streams
• Business friendly Apache 2-
license
Speedment Workflow
customers.stream()
.filter(…)
.filter(…)
.map(…)
.collect(toList());
Step 1: Generate
Code
Step 2: Write Logic Step 3: Run
Application
Step 4: Iterate
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Tool
Artifacts
• com.speedment:
• runtime
• generator
• tool
• speedment-maven-plugin
So How Do the Generated Code Work?
• Code is organized based on database structure
• Hash-sums make sure user changes are not overwritten
If the DB structure changes, the code is
updated with the press of a button
Entities, Managers and Applications
• An Entity represents a row in a table
• Is a POJO
• Customer
• CustomerImpl
• A Manager represents a table
• Responsible for the CRUD operations
• CustomerManager
• CustomerManagerImpl
• An Application represents the entire project
• Responsible for configuration and settings
• SalesApplication
• SalesApplicationBuilder
Querying the Database using Streams
• Queries are expressed
using Java 8 streams
• Streams are analyzed to
produce high-performance
queries
Expressing Queries as Streams
customers.stream()
.filter(Customer.REGION.equal(Region.NORTH_AMERICA))
.filter(Customer.REGISTERED.greaterOrEqual(startOfYear))
.count();
Standard Stream
API
Generated Enum
Constants
Only 1 value is loaded from
DB
Full Type-Safety
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
Querying the Database using Streams
SELECT * FROM 'customer'
REGION.equal(NORTH_AMERICA)
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT * FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
REGION.equal(NORTH_AMERICA)
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT * FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
count()
Sourc
e
Term.
Pipeline
Querying the Database using Streams
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
Sourc
e
Pipeline
Expressing Queries as Streams
// Gets the second page of customers in North America
// sorted by name in the form of a JSON array
“[“+
customers.stream()
.filter(REGION.equal(Region.NORTH_AMERICA))
.sorted(NAME.comparator())
.skip(10)
.limit(10) // JVM from here…
.map(JsonEncoder.allOf(customers)::apply)
.collect(joining(“, ”))
+”]”;
Expressing Queries as Streams
// Supports parallelism on custom executors
// with full control of thread work item layout
customers.stream()
.parallel()
.filter(REGION.equal(Region.NORTH_AMERICA))
.forEach(expensiveOperatation());
Application Example
• Total Count of Customers
• Located in North America
• Registered This Year
Step 1: Getting Speedment using Maven
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.0-EA</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
</dependencies>
</plugin>
Generate source files based on database
The JDBC connector to use
Step 2: Initializing Speedment
SalesApplication app = new SalesApplicationBuilder()
.withPassword("qwerty")
.build();
CustomerManager customers = app.getOrThrow(CustomerManager.class);
These classes are generated
automatically
Instance is configured using Builder-
pattern
A manager class is generated for every database table
Step 3: Querying
Region fromWhere = Region.NORTH_AMERICA;
Instant fromWhen = Instant.parse("2016-01-01");
long count = customers.stream()
.filter(Customer.REGION.equal(fromWhere))
.filter(Customer.REGISTERED.greaterOrEqual(fromWhen))
.count();
Step 4: Output
System.out.println(
"A total of %d customers from %s " +
"have registered this year.",
count, fromWhere.name()
);
Full Application
public static void main(String… args) {
SalesApplication app = new SalesApplicationBuilder()
.withPassword("qwerty")
.build();
CustomerManager customers = app.getOrThrow(CustomerManager.class);
Region fromWhere = Region.NORTH_AMERICA;
Instant fromWhen = Instant.parse("2016-01-01");
long count = customers.stream()
.filter(Customer.REGION.equal(fromWhere))
.filter(Customer.REGISTERED.greaterOrEqual(fromWhen))
.count();
System.out.println(
"A total of %d customers from %s " +
"have registered this year.",
count, fromWhere.name()
);
}
Output
Pers-MacBook-Pro:~ pemi$ java –jar salesapplication.jar
A total of 354 customers from NORTH_AMERICA have registered this year.
Live Demo: Speedment
• Generate Domain Model
• Write Java Stream that:
• Determine the ID of a certain city
• Alphabetical list of last names of
salespersons in that city
• Execute
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Controlling the Code Generation
• So far we have queried a
database with streams
• We have used code generation
to create entities and managers
• Can it be used for more?
What is Available out of the Box?
• MVC oriented code generation
• Modular design
• Database domain model
• JSON configuration (DSL)
• Java language namer
• Translator and TranslatorDecorator
• Maven goals
• Type mappers
MVC Oriented Code Generation
• Model
• File, Class, Interface, Enum, Field, Method, Constructor,
Type, Generic, Annotation, …
• View
• Renders a model to Java (or another language)
• Set code style using custom views
• Control
• AutoImport, AutoEquals, AutoJavadoc, SetGetAdd, FinalParameters
• Write custom controllers to automate recurring tasks
MVC Oriented Code Generation
• Separation of concerns
• Code generation is type safe
• Catch errors compile time
• Discover methods directly in the IDE
• Reuse code segments and controllers
Modular Design
Database Domain Model
• Project
• Dbms
• Schema
• Table
• Column
• PrimaryKey
• ForeignKey
• Index
List<Table> tables = project.dbmses()
.flatMap(Dbms::schemas)
.flatMap(Schema::tables)
.collect(toList());
JSON Configuration (DSL)
{
"config" : {
"name" : "sales",
"dbmses" : [{
"name" : "db0",
"typeName" : "MySQL",
"ipAddress" : "127.0.0.1",
"username" : "root",
"schemas" : [{
"name" : "sales",
"tables" : [
{ "name" : "city" },
{ "name" : "salesperson" }
]
}]
}]
}
}
Java Language Namer
• Camel caser: converts from “some_db_name” to
“someDbName”
• Java naming conventions: user, User and USER
• Detects keywords like “final”,”static” and escapes them
• Detects collisions
• Pluralizer: bag → bags, entity → entities, fish → fish
Translator and TranslatorDecorator
• Translator
• Renders a DB entity like a Table to a new Class or an Interface
• TranslatorDecorator
• Modifies an existing Class or Interface
Maven Goals
• speedment:tool
• Launches the graphical tool
• Allows customization of configuration model
• Code generation
• speedment:generate
• Code generation without launching the tool
• speedment:reload
• Reloads database metadata without launching the tool
• speedment:clear
• Removes all the generated classes (except manual changes) without launching the
tool
Type Mappers
• Controls how columns are implemented
• Runtime conversion between Database and Java types
java.sql.Timestamp long
Generation vs. Templates
• Separation of concerns
• Easily change code style
• Minimize maintenance
• Maximize reusability
Generate a New Custom Class
1. Create a new Translator
2. Model how the new class
should look
3. Define a Plugin Class
4. Include it in project pom.xml
Example: Generate a Point class
Step 1: Create a New Translator Class
public class PointTranslator extends
AbstractJavaClassTranslator<Project, Class> {
public final static TranslatorKey<Project, Class> POINT_KEY =
new TranslatorKey.of(“generated_point", Class.class);
public PointTranslator(Project document) { super(document, Class::of); }
@Override
protected Class makeCodeGenModel(File file) {
return newBuilder(file, getClassOrInterfaceName())
.forEveryProject((clazz, project) -> {
// Generate Content Here
}).build();
}
@Override
protected String getClassOrInterfaceName() { return ”Point"; }
@Override
protected String getJavadocRepresentText() { return "A 2-dimensional coordinate."; }
}
Every translator is identified by a
TranslatorKey
Name of generated class
Javadoc
Called every time the translator is invoked
forEvery(Project|Dbms|Schema|Table|Column|
…)
Step 2: The makeCodeGenModel -
methodclazz.public_()
.add(Field.of(“x”, int.class)
.private_().final_()
)
.add(Field.of(“y”, int.class)
.private_().final_()
)
.add(Constructor.of().public_()
.add(Field.of(“x”, int.class))
.add(Field.of(“y”, int.class))
.add(“this.x = x;”,
“this.y = y;”
)
)
.add(Method.of(“getX”, int.class).public_()
.add(“return x;”)
)
.add(Method.of(“getY”, int.class).public_()
.add(“return y;”)
)
.call(new AutoEquals<>())
.call(new AutoToString<>());
Step 3: Define a Plugin Class
public class PointPlugin {
@ExecuteBefore(RESOLVED)
protected void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
PointTranslator.POINT_KEY,
PointTranslator::new
);
}
}
The key defined earlier
Will execute when Speedment is
being initialized
How the translator is constructed
Step 4: Include it in Project pom.xml
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.0-EA</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>point-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<components>
<component>com.example.pointplugin.PointPlugin</component>
</components>
</configuration>
</plugin>
This tells Speedment to load the plugin
Make sure our plugin project is on the classpath
Execute
/**
* A 2-dimensional coordinate.
* <p>
* This file is safe to edit. It will not be overwritten by
the code generator.
*
* @author company
*/
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
The following file is generated: public int hashCode() {
int hashCode = 31;
hashCode += 41 * x;
hashCode += 41 * y;
return hashCode;
}
public Boolean equals(Object other) {
if (this == other) return true;
else if (other == null) return false;
else if (!(other instanceof Point)) {
return false;
}
final Point point = (Point) other;
return x == point.x && y == point.y;
}
public String toString() {
return new StringBuilder(“Point{”)
.append(“x: “).append(x).append(“, “)
.append(“y: “).append(y).append(“}”);
}
}
A More Concrete Example
1. Create a new Translator
2. Model how the new class
should look
3. Define a Plugin Class
4. Include it in project pom.xml
Example: Generate an Enum of
tables in the database
Step 1: Create a New Translator Class
public class TableEnumTranslator extends
AbstractJavaClassTranslator<Project, Enum> {
public final static TranslatorKey<Project, Enum> TABLES_ENUM_KEY =
new TranslatorKey.of(“tables_enum", Enum.class);
public TableEnumTranslator(Project document) { super(document, Enum::of); }
@Override
protected Enum makeCodeGenModel(File file) {
return newBuilder(file, getClassOrInterfaceName())
.forEveryProject((clazz, project) -> {
// Generate Content Here
}).build();
}
@Override
protected String getClassOrInterfaceName() { return ”Tables"; }
@Override
protected String getJavadocRepresentText() { return "An enumeration of tables in the database."; }
}
Every translator is identified by a
TranslatorKey
Name of generated class
Javadoc
Called every time the translator is invoked
forEvery(Project|Dbms|Schema|Table|Column|
…)
Step 2: The makeCodeGenModel -
method
DocumentDbUtil.traverseOver(project, Table.class)
.map(Table::getJavaName)
.map(getSupport().namer()::javaStaticFieldName)
.sorted()
.map(EnumConstant::of)
.forEachOrdered(clazz::add);
Step 3: Define a Plugin Class
public class TableEnumPlugin {
@ExecuteBefore(RESOLVED)
protected void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
TableEnumTranslator.TABLES_ENUM_KEY,
TableEnumTranslator::new
);
}
}
Step 4: Include it in Project pom.xml
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.0-EA</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>table-enum-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<components>
<component>com.example.tableenumplugin.TableEnumPlugin</component>
</components>
</configuration>
</plugin>
This tells Speedment to load the plugin
Make sure our plugin project is on the
classpath
Execute
/**
* An enumeration of tables in the database.
* <p>
* This file is safe to edit. It will not be overwritten by the code generator.
*
* @author company
*/
enum Tables {
CITY, SALESPERSON;
}
The following file is generated:
Generate all the Things
• Gson Adapters
• Spring Configuration Files
• REST Controllers
• and much more…
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Add New Method to Existing Classes
• So far we have
• Queried a database with generated
classes
• Generated a custom class
• How do we modify the existing
generation of classes?
Add New Method to Existing Classes
• Fit Into Existing Class Hierarchy
• Change Naming Conventions
• Optimize Internal Implementations
• Add Custom Methods
Add New Method to Existing Classes
Example: Add a getColumnCount
method to generated managers
1. Create a new
TranslatorDecorator class
2. Write code generation logic
3. Add it to Speedment
Step 1: Creating a New Decorator Class
public class ColumnCountDecorator implements TranslatorDecorator<Table, Interface> {
@Override
public void apply(JavaClassTranslator<Table, Interface> translator) {
translator.onMake(builder -> {
builder.forEveryTable((intrf, table) -> {
// Code generation logic goes here
});
});
}
}
Step 2: Write Code Generation Logic
int columnCount = table.columns().count();
intrf.add(Method.of("getColumnCount", int.class)
.default_()
.set(Javadoc.of("Returns the number of columns in this table.")
.add(RETURN.setValue("the column count"))
)
.add("return " + columnCount + ";")
);
Step 3: Add it to Speedment
public final class TableEnumPlugin {
@ExecuteBefore(RESOLVED)
protected void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
TableEnumTranslator.TABLES_ENUM_KEY,
TableEnumTranslator::new
);
codeGen.add(
Table.class,
StandardTranslatorKey.GENERATED_MANAGER,
new ColumnCountDecorator()
);
}
}
Modify an existing translator key
Our new decorator
The same plugin class as we
created earlier
Execute
When the project is
regenerated, a new method is
added to each manager
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Demo: Advanced Plugin
• Use the Speedment Spring
Plugin to generate a working
REST API
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
Additional Features
• Add GUI Tool components for
custom configuration
• Extend the JSON DSL
dynamically with plugins
• Automate your build
environment with Maven
• Add custom data type
mappers
Additional Features
• Plugin a custom namer
• Generate classes that are related to other domain models
• Generate classes for other languages
• Style the GUI Tool
Database Connectors
Open Source
• MySQL
• PostgreSQL
• MariaDB
Enterprise
• Oracle
• Microsoft SQL server
• dB2
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Hands on Demo
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Hands on Demo
• Additional Features
• Real World Examples
• Questions & Answers
In-JVM-Memory Data Store
• Alternative stream source
• Uses code generation
• Optimized serializers for
offheap storage
• No changes to user-written
code
• 10-100x faster queries
Ext Speeder
In-JVM-Memory !
Q&A
www.speedment.org
github.com/speedment
@speedment
www.speedment.com
Linkedin:
Per Minborg
Emil Forslund
1 de 76

Recomendados

JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516] por
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]Malin Weiss
103 visualizações50 slides
High-Performance Hibernate Devoxx France 2016 por
High-Performance Hibernate Devoxx France 2016High-Performance Hibernate Devoxx France 2016
High-Performance Hibernate Devoxx France 2016Vlad Mihalcea
17.3K visualizações49 slides
High-Performance JDBC Voxxed Bucharest 2016 por
High-Performance JDBC Voxxed Bucharest 2016High-Performance JDBC Voxxed Bucharest 2016
High-Performance JDBC Voxxed Bucharest 2016Vlad Mihalcea
11.8K visualizações58 slides
TPC-H in MongoDB por
TPC-H in MongoDBTPC-H in MongoDB
TPC-H in MongoDBAung Thu Rha Hein
3.8K visualizações17 slides
Sql server 2016 it just runs faster sql bits 2017 edition por
Sql server 2016 it just runs faster   sql bits 2017 editionSql server 2016 it just runs faster   sql bits 2017 edition
Sql server 2016 it just runs faster sql bits 2017 editionBob Ward
662 visualizações53 slides
Serialization and performance in Java por
Serialization and performance in JavaSerialization and performance in Java
Serialization and performance in JavaStrannik_2013
8.1K visualizações52 slides

Mais conteúdo relacionado

Mais procurados

High Performance Hibernate JavaZone 2016 por
High Performance Hibernate JavaZone 2016High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016Vlad Mihalcea
4K visualizações68 slides
Brk3288 sql server v.next with support on linux, windows and containers was... por
Brk3288 sql server v.next with support on linux, windows and containers   was...Brk3288 sql server v.next with support on linux, windows and containers   was...
Brk3288 sql server v.next with support on linux, windows and containers was...Bob Ward
752 visualizações35 slides
User Defined Partitioning on PlazmaDB por
User Defined Partitioning on PlazmaDBUser Defined Partitioning on PlazmaDB
User Defined Partitioning on PlazmaDBKai Sasaki
1.4K visualizações28 slides
Real World Experience: Integrating DB2 with XPages por
Real World Experience: Integrating DB2 with XPagesReal World Experience: Integrating DB2 with XPages
Real World Experience: Integrating DB2 with XPagesSteve_Zavocki
1.2K visualizações49 slides
Inside sql server in memory oltp sql sat nyc 2017 por
Inside sql server in memory oltp sql sat nyc 2017Inside sql server in memory oltp sql sat nyc 2017
Inside sql server in memory oltp sql sat nyc 2017Bob Ward
636 visualizações46 slides
Experience sql server on l inux and docker por
Experience sql server on l inux and dockerExperience sql server on l inux and docker
Experience sql server on l inux and dockerBob Ward
690 visualizações23 slides

Mais procurados(20)

High Performance Hibernate JavaZone 2016 por Vlad Mihalcea
High Performance Hibernate JavaZone 2016High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016
Vlad Mihalcea4K visualizações
Brk3288 sql server v.next with support on linux, windows and containers was... por Bob Ward
Brk3288 sql server v.next with support on linux, windows and containers   was...Brk3288 sql server v.next with support on linux, windows and containers   was...
Brk3288 sql server v.next with support on linux, windows and containers was...
Bob Ward752 visualizações
User Defined Partitioning on PlazmaDB por Kai Sasaki
User Defined Partitioning on PlazmaDBUser Defined Partitioning on PlazmaDB
User Defined Partitioning on PlazmaDB
Kai Sasaki1.4K visualizações
Real World Experience: Integrating DB2 with XPages por Steve_Zavocki
Real World Experience: Integrating DB2 with XPagesReal World Experience: Integrating DB2 with XPages
Real World Experience: Integrating DB2 with XPages
Steve_Zavocki1.2K visualizações
Inside sql server in memory oltp sql sat nyc 2017 por Bob Ward
Inside sql server in memory oltp sql sat nyc 2017Inside sql server in memory oltp sql sat nyc 2017
Inside sql server in memory oltp sql sat nyc 2017
Bob Ward636 visualizações
Experience sql server on l inux and docker por Bob Ward
Experience sql server on l inux and dockerExperience sql server on l inux and docker
Experience sql server on l inux and docker
Bob Ward690 visualizações
Gs08 modernize your data platform with sql technologies wash dc por Bob Ward
Gs08 modernize your data platform with sql technologies   wash dcGs08 modernize your data platform with sql technologies   wash dc
Gs08 modernize your data platform with sql technologies wash dc
Bob Ward815 visualizações
WebLogic Scripting Tool Overview por James Bayer
WebLogic Scripting Tool OverviewWebLogic Scripting Tool Overview
WebLogic Scripting Tool Overview
James Bayer22.7K visualizações
Brk2051 sql server on linux and docker por Bob Ward
Brk2051 sql server on linux and dockerBrk2051 sql server on linux and docker
Brk2051 sql server on linux and docker
Bob Ward2.7K visualizações
High Performance Computing - Cloud Point of View por aragozin
High Performance Computing - Cloud Point of ViewHigh Performance Computing - Cloud Point of View
High Performance Computing - Cloud Point of View
aragozin1.7K visualizações
77739818 troubleshooting-web-logic-103 por shashank_ibm
77739818 troubleshooting-web-logic-10377739818 troubleshooting-web-logic-103
77739818 troubleshooting-web-logic-103
shashank_ibm4.7K visualizações
Sizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-Final por Vigyan Jain
Sizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-FinalSizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-Final
Sizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-Final
Vigyan Jain395 visualizações
Boost Development With Java EE7 On EAP7 (Demitris Andreadis) por Red Hat Developers
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Red Hat Developers1.9K visualizações
SQL Server In-Memory OLTP: What Every SQL Professional Should Know por Bob Ward
SQL Server In-Memory OLTP: What Every SQL Professional Should KnowSQL Server In-Memory OLTP: What Every SQL Professional Should Know
SQL Server In-Memory OLTP: What Every SQL Professional Should Know
Bob Ward704 visualizações
Compare DynamoDB vs. MongoDB por Amar Das
Compare DynamoDB vs. MongoDBCompare DynamoDB vs. MongoDB
Compare DynamoDB vs. MongoDB
Amar Das9.4K visualizações
Inside SQL Server In-Memory OLTP por Bob Ward
Inside SQL Server In-Memory OLTPInside SQL Server In-Memory OLTP
Inside SQL Server In-Memory OLTP
Bob Ward2.6K visualizações
MongoDB - An Agile NoSQL Database por Gaurav Awasthi
MongoDB - An Agile NoSQL DatabaseMongoDB - An Agile NoSQL Database
MongoDB - An Agile NoSQL Database
Gaurav Awasthi3.6K visualizações
Migrating to postgresql por botsplash.com
Migrating to postgresqlMigrating to postgresql
Migrating to postgresql
botsplash.com205 visualizações
Tagging search solution design por Alexander Tokarev
Tagging search solution designTagging search solution design
Tagging search solution design
Alexander Tokarev576 visualizações

Similar a JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4489]

Silicon Valley JUG - How to generate customized java 8 code from your database por
Silicon Valley JUG - How to generate customized java 8 code from your databaseSilicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your databaseSpeedment, Inc.
267 visualizações79 slides
How to generate customized java 8 code from your database por
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseSpeedment, Inc.
1.4K visualizações79 slides
Intro to .NET for Government Developers por
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government DevelopersFrank La Vigne
846 visualizações69 slides
Play Framework and Activator por
Play Framework and ActivatorPlay Framework and Activator
Play Framework and ActivatorKevin Webber
4.1K visualizações47 slides
Tech io spa_angularjs_20130814_v0.9.5 por
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Ganesh Kondal
1.5K visualizações42 slides
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes por
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesMalin Weiss
50 visualizações38 slides

Similar a JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4489](20)

Silicon Valley JUG - How to generate customized java 8 code from your database por Speedment, Inc.
Silicon Valley JUG - How to generate customized java 8 code from your databaseSilicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your database
Speedment, Inc.267 visualizações
How to generate customized java 8 code from your database por Speedment, Inc.
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your database
Speedment, Inc.1.4K visualizações
Intro to .NET for Government Developers por Frank La Vigne
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
Frank La Vigne846 visualizações
Play Framework and Activator por Kevin Webber
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
Kevin Webber4.1K visualizações
Tech io spa_angularjs_20130814_v0.9.5 por Ganesh Kondal
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5
Ganesh Kondal1.5K visualizações
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes por Malin Weiss
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
Malin Weiss50 visualizações
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes por Speedment, Inc.
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
Speedment, Inc.327 visualizações
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi... por Sencha
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
Sencha336 visualizações
Web Development using Ruby on Rails por Avi Kedar
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
Avi Kedar628 visualizações
05 entity framework por Bat Programmer
05 entity framework05 entity framework
05 entity framework
Bat Programmer607 visualizações
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach por PROIDEA
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav TulachJDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach
PROIDEA124 visualizações
Masterin Large Scale Java Script Applications por Fabian Jakobs
Masterin Large Scale Java Script ApplicationsMasterin Large Scale Java Script Applications
Masterin Large Scale Java Script Applications
Fabian Jakobs1.9K visualizações
How to Contribute to Apache Usergrid por David M. Johnson
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache Usergrid
David M. Johnson9.8K visualizações
Quick start with AngularJS por Iuliia Baranova
Quick start with AngularJSQuick start with AngularJS
Quick start with AngularJS
Iuliia Baranova800 visualizações
Java script nirvana in netbeans [con5679] por Ryan Cuprak
Java script nirvana in netbeans [con5679]Java script nirvana in netbeans [con5679]
Java script nirvana in netbeans [con5679]
Ryan Cuprak1.1K visualizações
Bringing DevOps to the Database por Michaela Murray
Bringing DevOps to the DatabaseBringing DevOps to the Database
Bringing DevOps to the Database
Michaela Murray143 visualizações
Escaping the yellow bubble - rewriting Domino using MongoDb and Angular por Mark Leusink
Escaping the yellow bubble - rewriting Domino using MongoDb and AngularEscaping the yellow bubble - rewriting Domino using MongoDb and Angular
Escaping the yellow bubble - rewriting Domino using MongoDb and Angular
Mark Leusink5K visualizações
MEAN Stack Warm-up por Troy Miles
MEAN Stack Warm-upMEAN Stack Warm-up
MEAN Stack Warm-up
Troy Miles379 visualizações
Internship softwaretraining@ijse por Jinadi Rashmika
Internship softwaretraining@ijseInternship softwaretraining@ijse
Internship softwaretraining@ijse
Jinadi Rashmika181 visualizações
SharePoint 2013 Performance Analysis - Robi Vončina por SPC Adriatics
SharePoint 2013 Performance Analysis - Robi VončinaSharePoint 2013 Performance Analysis - Robi Vončina
SharePoint 2013 Performance Analysis - Robi Vončina
SPC Adriatics6.5K visualizações

Mais de Speedment, Inc.

SenchaCon Roadshow Irvine 2017 por
SenchaCon Roadshow Irvine 2017SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017Speedment, Inc.
180 visualizações42 slides
NYJavaSIG - Big Data Microservices w/ Speedment por
NYJavaSIG - Big Data Microservices w/ SpeedmentNYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ SpeedmentSpeedment, Inc.
391 visualizações54 slides
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516] por
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]Speedment, Inc.
206 visualizações50 slides
DZone Java 8 Block Buster: Query Databases Using Streams por
DZone Java 8 Block Buster: Query Databases Using StreamsDZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using StreamsSpeedment, Inc.
1.1K visualizações61 slides
Speed-up Your Big Data Applications with Sencha and Speedment por
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeedment, Inc.
736 visualizações19 slides
Speedment & Sencha at Oracle Open World 2015 por
Speedment & Sencha at Oracle Open World 2015Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015Speedment, Inc.
512 visualizações16 slides

Mais de Speedment, Inc.(11)

SenchaCon Roadshow Irvine 2017 por Speedment, Inc.
SenchaCon Roadshow Irvine 2017SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017
Speedment, Inc.180 visualizações
NYJavaSIG - Big Data Microservices w/ Speedment por Speedment, Inc.
NYJavaSIG - Big Data Microservices w/ SpeedmentNYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ Speedment
Speedment, Inc.391 visualizações
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516] por Speedment, Inc.
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
Speedment, Inc.206 visualizações
DZone Java 8 Block Buster: Query Databases Using Streams por Speedment, Inc.
DZone Java 8 Block Buster: Query Databases Using StreamsDZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using Streams
Speedment, Inc.1.1K visualizações
Speed-up Your Big Data Applications with Sencha and Speedment por Speedment, Inc.
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and Speedment
Speedment, Inc.736 visualizações
Speedment & Sencha at Oracle Open World 2015 por Speedment, Inc.
Speedment & Sencha at Oracle Open World 2015Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015
Speedment, Inc.512 visualizações
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs por Speedment, Inc.
Java one2015 - Work With Hundreds of Hot Terabytes in JVMsJava one2015 - Work With Hundreds of Hot Terabytes in JVMs
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs
Speedment, Inc.1.6K visualizações
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015 por Speedment, Inc.
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
Speedment, Inc.1.4K visualizações
Speedment - Reactive programming for Java8 por Speedment, Inc.
Speedment - Reactive programming for Java8Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8
Speedment, Inc.1.4K visualizações
Java days gbg online por Speedment, Inc.
Java days gbg onlineJava days gbg online
Java days gbg online
Speedment, Inc.384 visualizações
SAP Open Source meetup/Speedment - Palo Alto 2015 por Speedment, Inc.
SAP Open Source meetup/Speedment - Palo Alto 2015SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015
Speedment, Inc.740 visualizações

Último

2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue por
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlueShapeBlue
103 visualizações23 slides
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... por
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...James Anderson
156 visualizações32 slides
Network Source of Truth and Infrastructure as Code revisited por
Network Source of Truth and Infrastructure as Code revisitedNetwork Source of Truth and Infrastructure as Code revisited
Network Source of Truth and Infrastructure as Code revisitedNetwork Automation Forum
52 visualizações45 slides
20231123_Camunda Meetup Vienna.pdf por
20231123_Camunda Meetup Vienna.pdf20231123_Camunda Meetup Vienna.pdf
20231123_Camunda Meetup Vienna.pdfPhactum Softwareentwicklung GmbH
50 visualizações73 slides
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue por
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlueCloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlueShapeBlue
93 visualizações15 slides
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... por
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...ShapeBlue
120 visualizações13 slides

Último(20)

2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue por ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
ShapeBlue103 visualizações
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... por James Anderson
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
James Anderson156 visualizações
Network Source of Truth and Infrastructure as Code revisited por Network Automation Forum
Network Source of Truth and Infrastructure as Code revisitedNetwork Source of Truth and Infrastructure as Code revisited
Network Source of Truth and Infrastructure as Code revisited
Network Automation Forum52 visualizações
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue por ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlueCloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
ShapeBlue93 visualizações
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... por ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue120 visualizações
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or... por ShapeBlue
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
ShapeBlue158 visualizações
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... por TrustArc
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc160 visualizações
NTGapps NTG LowCode Platform por Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu365 visualizações
Business Analyst Series 2023 - Week 4 Session 7 por DianaGray10
Business Analyst Series 2023 -  Week 4 Session 7Business Analyst Series 2023 -  Week 4 Session 7
Business Analyst Series 2023 - Week 4 Session 7
DianaGray10126 visualizações
Kyo - Functional Scala 2023.pdf por Flavio W. Brasil
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdf
Flavio W. Brasil449 visualizações
Digital Personal Data Protection (DPDP) Practical Approach For CISOs por Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash153 visualizações
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue por ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueMigrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
ShapeBlue176 visualizações
Extending KVM Host HA for Non-NFS Storage - Alex Ivanov - StorPool por ShapeBlue
Extending KVM Host HA for Non-NFS Storage -  Alex Ivanov - StorPoolExtending KVM Host HA for Non-NFS Storage -  Alex Ivanov - StorPool
Extending KVM Host HA for Non-NFS Storage - Alex Ivanov - StorPool
ShapeBlue84 visualizações
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue por ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueElevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
ShapeBlue179 visualizações
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... por ShapeBlue
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
ShapeBlue146 visualizações
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T por ShapeBlue
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TCloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
ShapeBlue112 visualizações
Data Integrity for Banking and Financial Services por Precisely
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial Services
Precisely78 visualizações
DRBD Deep Dive - Philipp Reisner - LINBIT por ShapeBlue
DRBD Deep Dive - Philipp Reisner - LINBITDRBD Deep Dive - Philipp Reisner - LINBIT
DRBD Deep Dive - Philipp Reisner - LINBIT
ShapeBlue140 visualizações
The Role of Patterns in the Era of Large Language Models por Yunyao Li
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language Models
Yunyao Li80 visualizações

JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4489]

  • 1. Tutorial: How to Generate Customized Java 8 Code from Your Database Per Minborg CTO, Speedment, Inc Emil Forslund Developer, Speedment, Inc.
  • 2. Every Decision a Developer Makes is a Trade-off The best code is no code at all
  • 3. Using Code Generation • Makes the code efficient and short • Modifications are done once and applied everywhere • Minimizes errors • “DRY” (Don’t Repeat Yourself) vs. ”WET” (We Enjoy Typing) • “Code your code” But how can we control the generated code?
  • 4. About Us Per Minborg • Founder of several IT companies • Lives in Palo Alto • 20 years of Java experience • 15+ US patents • Speaker at Java events • Blog: Minborg’s Java Pot Emil Forslund • Java Developer • Lives in Palo Alto • 8 years of Java experience • Speaker at Java events • Blog: Age of Java Spire • Speedment Open Source mascot • Lives on GitHub • 1.5 years of mascot experience
  • 5. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 6. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 7. Do You Recognize This Code? Class.forName("org.postgresql.Driver"); try (final Connection conn = DriverManager.getConnection( "jdbc:postgresql://hostname:port/dbname", "username", "password")) { // Database Logic Here... }
  • 8. Why Creating DB-Apps is So Time Consuming • Even trivial database operations require a lot of boilerplate code • Mixing SQL and Java is error-prone • ORMs require you to write annotated POJOs for every table • Creating even a simple DB app can take hours
  • 9. Open-Source Project Speedment • Stream ORM Java toolkit and runtime • Generate domain-model from the database • No need for complicated configurations or setup • All operations are type-safe • Data is accessed using Java 8 Streams • Business friendly Apache 2- license
  • 10. Speedment Workflow customers.stream() .filter(…) .filter(…) .map(…) .collect(toList()); Step 1: Generate Code Step 2: Write Logic Step 3: Run Application Step 4: Iterate
  • 11. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 12. Tool
  • 13. Artifacts • com.speedment: • runtime • generator • tool • speedment-maven-plugin
  • 14. So How Do the Generated Code Work? • Code is organized based on database structure • Hash-sums make sure user changes are not overwritten If the DB structure changes, the code is updated with the press of a button
  • 15. Entities, Managers and Applications • An Entity represents a row in a table • Is a POJO • Customer • CustomerImpl • A Manager represents a table • Responsible for the CRUD operations • CustomerManager • CustomerManagerImpl • An Application represents the entire project • Responsible for configuration and settings • SalesApplication • SalesApplicationBuilder
  • 16. Querying the Database using Streams • Queries are expressed using Java 8 streams • Streams are analyzed to produce high-performance queries
  • 17. Expressing Queries as Streams customers.stream() .filter(Customer.REGION.equal(Region.NORTH_AMERICA)) .filter(Customer.REGISTERED.greaterOrEqual(startOfYear)) .count(); Standard Stream API Generated Enum Constants Only 1 value is loaded from DB Full Type-Safety SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’;
  • 18. Querying the Database using Streams SELECT * FROM 'customer' REGION.equal(NORTH_AMERICA) REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Filter Term. Pipeline
  • 19. Querying the Database using Streams SELECT * FROM 'customer' WHERE 'customer'.'region' = ‘North America’ REGION.equal(NORTH_AMERICA) REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Filter Term. Pipeline
  • 20. Querying the Database using Streams SELECT * FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Term. Pipeline
  • 21. Querying the Database using Streams SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; count() Sourc e Term. Pipeline
  • 22. Querying the Database using Streams SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; Sourc e Pipeline
  • 23. Expressing Queries as Streams // Gets the second page of customers in North America // sorted by name in the form of a JSON array “[“+ customers.stream() .filter(REGION.equal(Region.NORTH_AMERICA)) .sorted(NAME.comparator()) .skip(10) .limit(10) // JVM from here… .map(JsonEncoder.allOf(customers)::apply) .collect(joining(“, ”)) +”]”;
  • 24. Expressing Queries as Streams // Supports parallelism on custom executors // with full control of thread work item layout customers.stream() .parallel() .filter(REGION.equal(Region.NORTH_AMERICA)) .forEach(expensiveOperatation());
  • 25. Application Example • Total Count of Customers • Located in North America • Registered This Year
  • 26. Step 1: Getting Speedment using Maven <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.0-EA</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> </dependencies> </plugin> Generate source files based on database The JDBC connector to use
  • 27. Step 2: Initializing Speedment SalesApplication app = new SalesApplicationBuilder() .withPassword("qwerty") .build(); CustomerManager customers = app.getOrThrow(CustomerManager.class); These classes are generated automatically Instance is configured using Builder- pattern A manager class is generated for every database table
  • 28. Step 3: Querying Region fromWhere = Region.NORTH_AMERICA; Instant fromWhen = Instant.parse("2016-01-01"); long count = customers.stream() .filter(Customer.REGION.equal(fromWhere)) .filter(Customer.REGISTERED.greaterOrEqual(fromWhen)) .count();
  • 29. Step 4: Output System.out.println( "A total of %d customers from %s " + "have registered this year.", count, fromWhere.name() );
  • 30. Full Application public static void main(String… args) { SalesApplication app = new SalesApplicationBuilder() .withPassword("qwerty") .build(); CustomerManager customers = app.getOrThrow(CustomerManager.class); Region fromWhere = Region.NORTH_AMERICA; Instant fromWhen = Instant.parse("2016-01-01"); long count = customers.stream() .filter(Customer.REGION.equal(fromWhere)) .filter(Customer.REGISTERED.greaterOrEqual(fromWhen)) .count(); System.out.println( "A total of %d customers from %s " + "have registered this year.", count, fromWhere.name() ); }
  • 31. Output Pers-MacBook-Pro:~ pemi$ java –jar salesapplication.jar A total of 354 customers from NORTH_AMERICA have registered this year.
  • 32. Live Demo: Speedment • Generate Domain Model • Write Java Stream that: • Determine the ID of a certain city • Alphabetical list of last names of salespersons in that city • Execute
  • 33. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 34. Controlling the Code Generation • So far we have queried a database with streams • We have used code generation to create entities and managers • Can it be used for more?
  • 35. What is Available out of the Box? • MVC oriented code generation • Modular design • Database domain model • JSON configuration (DSL) • Java language namer • Translator and TranslatorDecorator • Maven goals • Type mappers
  • 36. MVC Oriented Code Generation • Model • File, Class, Interface, Enum, Field, Method, Constructor, Type, Generic, Annotation, … • View • Renders a model to Java (or another language) • Set code style using custom views • Control • AutoImport, AutoEquals, AutoJavadoc, SetGetAdd, FinalParameters • Write custom controllers to automate recurring tasks
  • 37. MVC Oriented Code Generation • Separation of concerns • Code generation is type safe • Catch errors compile time • Discover methods directly in the IDE • Reuse code segments and controllers
  • 39. Database Domain Model • Project • Dbms • Schema • Table • Column • PrimaryKey • ForeignKey • Index List<Table> tables = project.dbmses() .flatMap(Dbms::schemas) .flatMap(Schema::tables) .collect(toList());
  • 40. JSON Configuration (DSL) { "config" : { "name" : "sales", "dbmses" : [{ "name" : "db0", "typeName" : "MySQL", "ipAddress" : "127.0.0.1", "username" : "root", "schemas" : [{ "name" : "sales", "tables" : [ { "name" : "city" }, { "name" : "salesperson" } ] }] }] } }
  • 41. Java Language Namer • Camel caser: converts from “some_db_name” to “someDbName” • Java naming conventions: user, User and USER • Detects keywords like “final”,”static” and escapes them • Detects collisions • Pluralizer: bag → bags, entity → entities, fish → fish
  • 42. Translator and TranslatorDecorator • Translator • Renders a DB entity like a Table to a new Class or an Interface • TranslatorDecorator • Modifies an existing Class or Interface
  • 43. Maven Goals • speedment:tool • Launches the graphical tool • Allows customization of configuration model • Code generation • speedment:generate • Code generation without launching the tool • speedment:reload • Reloads database metadata without launching the tool • speedment:clear • Removes all the generated classes (except manual changes) without launching the tool
  • 44. Type Mappers • Controls how columns are implemented • Runtime conversion between Database and Java types java.sql.Timestamp long
  • 45. Generation vs. Templates • Separation of concerns • Easily change code style • Minimize maintenance • Maximize reusability
  • 46. Generate a New Custom Class 1. Create a new Translator 2. Model how the new class should look 3. Define a Plugin Class 4. Include it in project pom.xml Example: Generate a Point class
  • 47. Step 1: Create a New Translator Class public class PointTranslator extends AbstractJavaClassTranslator<Project, Class> { public final static TranslatorKey<Project, Class> POINT_KEY = new TranslatorKey.of(“generated_point", Class.class); public PointTranslator(Project document) { super(document, Class::of); } @Override protected Class makeCodeGenModel(File file) { return newBuilder(file, getClassOrInterfaceName()) .forEveryProject((clazz, project) -> { // Generate Content Here }).build(); } @Override protected String getClassOrInterfaceName() { return ”Point"; } @Override protected String getJavadocRepresentText() { return "A 2-dimensional coordinate."; } } Every translator is identified by a TranslatorKey Name of generated class Javadoc Called every time the translator is invoked forEvery(Project|Dbms|Schema|Table|Column| …)
  • 48. Step 2: The makeCodeGenModel - methodclazz.public_() .add(Field.of(“x”, int.class) .private_().final_() ) .add(Field.of(“y”, int.class) .private_().final_() ) .add(Constructor.of().public_() .add(Field.of(“x”, int.class)) .add(Field.of(“y”, int.class)) .add(“this.x = x;”, “this.y = y;” ) ) .add(Method.of(“getX”, int.class).public_() .add(“return x;”) ) .add(Method.of(“getY”, int.class).public_() .add(“return y;”) ) .call(new AutoEquals<>()) .call(new AutoToString<>());
  • 49. Step 3: Define a Plugin Class public class PointPlugin { @ExecuteBefore(RESOLVED) protected void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, PointTranslator.POINT_KEY, PointTranslator::new ); } } The key defined earlier Will execute when Speedment is being initialized How the translator is constructed
  • 50. Step 4: Include it in Project pom.xml <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.0-EA</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <dependency> <groupId>com.example</groupId> <artifactId>point-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> <configuration> <components> <component>com.example.pointplugin.PointPlugin</component> </components> </configuration> </plugin> This tells Speedment to load the plugin Make sure our plugin project is on the classpath
  • 51. Execute /** * A 2-dimensional coordinate. * <p> * This file is safe to edit. It will not be overwritten by the code generator. * * @author company */ public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } The following file is generated: public int hashCode() { int hashCode = 31; hashCode += 41 * x; hashCode += 41 * y; return hashCode; } public Boolean equals(Object other) { if (this == other) return true; else if (other == null) return false; else if (!(other instanceof Point)) { return false; } final Point point = (Point) other; return x == point.x && y == point.y; } public String toString() { return new StringBuilder(“Point{”) .append(“x: “).append(x).append(“, “) .append(“y: “).append(y).append(“}”); } }
  • 52. A More Concrete Example 1. Create a new Translator 2. Model how the new class should look 3. Define a Plugin Class 4. Include it in project pom.xml Example: Generate an Enum of tables in the database
  • 53. Step 1: Create a New Translator Class public class TableEnumTranslator extends AbstractJavaClassTranslator<Project, Enum> { public final static TranslatorKey<Project, Enum> TABLES_ENUM_KEY = new TranslatorKey.of(“tables_enum", Enum.class); public TableEnumTranslator(Project document) { super(document, Enum::of); } @Override protected Enum makeCodeGenModel(File file) { return newBuilder(file, getClassOrInterfaceName()) .forEveryProject((clazz, project) -> { // Generate Content Here }).build(); } @Override protected String getClassOrInterfaceName() { return ”Tables"; } @Override protected String getJavadocRepresentText() { return "An enumeration of tables in the database."; } } Every translator is identified by a TranslatorKey Name of generated class Javadoc Called every time the translator is invoked forEvery(Project|Dbms|Schema|Table|Column| …)
  • 54. Step 2: The makeCodeGenModel - method DocumentDbUtil.traverseOver(project, Table.class) .map(Table::getJavaName) .map(getSupport().namer()::javaStaticFieldName) .sorted() .map(EnumConstant::of) .forEachOrdered(clazz::add);
  • 55. Step 3: Define a Plugin Class public class TableEnumPlugin { @ExecuteBefore(RESOLVED) protected void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, TableEnumTranslator.TABLES_ENUM_KEY, TableEnumTranslator::new ); } }
  • 56. Step 4: Include it in Project pom.xml <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.0-EA</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <dependency> <groupId>com.example</groupId> <artifactId>table-enum-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> <configuration> <components> <component>com.example.tableenumplugin.TableEnumPlugin</component> </components> </configuration> </plugin> This tells Speedment to load the plugin Make sure our plugin project is on the classpath
  • 57. Execute /** * An enumeration of tables in the database. * <p> * This file is safe to edit. It will not be overwritten by the code generator. * * @author company */ enum Tables { CITY, SALESPERSON; } The following file is generated:
  • 58. Generate all the Things • Gson Adapters • Spring Configuration Files • REST Controllers • and much more…
  • 59. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 60. Add New Method to Existing Classes • So far we have • Queried a database with generated classes • Generated a custom class • How do we modify the existing generation of classes?
  • 61. Add New Method to Existing Classes • Fit Into Existing Class Hierarchy • Change Naming Conventions • Optimize Internal Implementations • Add Custom Methods
  • 62. Add New Method to Existing Classes Example: Add a getColumnCount method to generated managers 1. Create a new TranslatorDecorator class 2. Write code generation logic 3. Add it to Speedment
  • 63. Step 1: Creating a New Decorator Class public class ColumnCountDecorator implements TranslatorDecorator<Table, Interface> { @Override public void apply(JavaClassTranslator<Table, Interface> translator) { translator.onMake(builder -> { builder.forEveryTable((intrf, table) -> { // Code generation logic goes here }); }); } }
  • 64. Step 2: Write Code Generation Logic int columnCount = table.columns().count(); intrf.add(Method.of("getColumnCount", int.class) .default_() .set(Javadoc.of("Returns the number of columns in this table.") .add(RETURN.setValue("the column count")) ) .add("return " + columnCount + ";") );
  • 65. Step 3: Add it to Speedment public final class TableEnumPlugin { @ExecuteBefore(RESOLVED) protected void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, TableEnumTranslator.TABLES_ENUM_KEY, TableEnumTranslator::new ); codeGen.add( Table.class, StandardTranslatorKey.GENERATED_MANAGER, new ColumnCountDecorator() ); } } Modify an existing translator key Our new decorator The same plugin class as we created earlier
  • 66. Execute When the project is regenerated, a new method is added to each manager
  • 67. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 68. Demo: Advanced Plugin • Use the Speedment Spring Plugin to generate a working REST API
  • 69. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 70. Additional Features • Add GUI Tool components for custom configuration • Extend the JSON DSL dynamically with plugins • Automate your build environment with Maven • Add custom data type mappers
  • 71. Additional Features • Plugin a custom namer • Generate classes that are related to other domain models • Generate classes for other languages • Style the GUI Tool
  • 72. Database Connectors Open Source • MySQL • PostgreSQL • MariaDB Enterprise • Oracle • Microsoft SQL server • dB2
  • 73. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Hands on Demo • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Hands on Demo • Additional Features • Real World Examples • Questions & Answers
  • 74. In-JVM-Memory Data Store • Alternative stream source • Uses code generation • Optimized serializers for offheap storage • No changes to user-written code • 10-100x faster queries

Notas do Editor

  1. What we are going to talk about today
  2. What we are going to talk about today
  3. Ice-breaker
  4. Negatives
  5. Positives
  6. Agile Workflow
  7. What we are going to talk about today
  8. Positives
  9. Positives
  10. Code Structure Let the database be the center of the iterative process
  11. What we are going to talk about today
  12. Pause before the fourth arrow ”Do you know what the coolest aspect of this paragraph is?”
  13. Positives
  14. Positives
  15. Output on next slide
  16. Output on next slide
  17. Output on next slide
  18. Next: Emil Live Demo #1
  19. What we are going to talk about today
  20. Stop here
  21. Mention problem before showing the solutions
  22. @ExecuteBefore says this class must be configured before use Dependency injection is used to get access to the code generation component
  23. @ExecuteBefore says this class must be configured before use Dependency injection is used to get access to the code generation component
  24. Now that you have seen all this, how do you think code generation can solve your challenges? Do you have ideas what you can generate?
  25. What we are going to talk about today
  26. Entities, Managers, Application
  27. Why add methods? You know your own domain model best!
  28. For every table! Like 100 tables!
  29. What we are going to talk about today
  30. Live Demo, then Q&A
  31. What we are going to talk about today
  32. Live Demo, then Q&A
  33. Live Demo, then Q&A
  34. What we are going to talk about today
  35. Live Demo, then Q&A