SlideShare ist ein Scribd-Unternehmen logo
1 von 76
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

Weitere ähnliche Inhalte

Was ist angesagt?

77739818 troubleshooting-web-logic-103
77739818 troubleshooting-web-logic-10377739818 troubleshooting-web-logic-103
77739818 troubleshooting-web-logic-103
shashank_ibm
 
Sizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-Final
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 Jain
 

Was ist angesagt? (20)

High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016
 
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...
Brk3288 sql server v.next with support on linux, windows and containers was...
 
User Defined Partitioning on PlazmaDB
User Defined Partitioning on PlazmaDBUser Defined Partitioning on PlazmaDB
User Defined Partitioning on PlazmaDB
 
Real World Experience: Integrating DB2 with XPages
Real World Experience: Integrating DB2 with XPagesReal World Experience: Integrating DB2 with XPages
Real World Experience: Integrating DB2 with XPages
 
Inside sql server in memory oltp sql sat nyc 2017
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
 
Experience sql server on l inux and docker
Experience sql server on l inux and dockerExperience sql server on l inux and docker
Experience sql server on l inux and docker
 
Hibernate performance tuning
Hibernate performance tuningHibernate performance tuning
Hibernate performance tuning
 
Gs08 modernize your data platform with sql technologies wash dc
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
 
WebLogic Scripting Tool Overview
WebLogic Scripting Tool OverviewWebLogic Scripting Tool Overview
WebLogic Scripting Tool Overview
 
Brk2051 sql server on linux and docker
Brk2051 sql server on linux and dockerBrk2051 sql server on linux and docker
Brk2051 sql server on linux and docker
 
High Performance Computing - Cloud Point of View
High Performance Computing - Cloud Point of ViewHigh Performance Computing - Cloud Point of View
High Performance Computing - Cloud Point of View
 
77739818 troubleshooting-web-logic-103
77739818 troubleshooting-web-logic-10377739818 troubleshooting-web-logic-103
77739818 troubleshooting-web-logic-103
 
Sizing MongoDB on AWS with Wired Tiger-Patrick and Vigyan-Final
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
 
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)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
 
SQL Server In-Memory OLTP: What Every SQL Professional Should Know
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
 
Compare DynamoDB vs. MongoDB
Compare DynamoDB vs. MongoDBCompare DynamoDB vs. MongoDB
Compare DynamoDB vs. MongoDB
 
Inside SQL Server In-Memory OLTP
Inside SQL Server In-Memory OLTPInside SQL Server In-Memory OLTP
Inside SQL Server In-Memory OLTP
 
MongoDB - An Agile NoSQL Database
MongoDB - An Agile NoSQL DatabaseMongoDB - An Agile NoSQL Database
MongoDB - An Agile NoSQL Database
 
Migrating to postgresql
Migrating to postgresqlMigrating to postgresql
Migrating to postgresql
 
Tagging search solution design
Tagging search solution designTagging search solution design
Tagging search solution design
 

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

Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5
Ganesh Kondal
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
Avi Kedar
 

Ähnlich wie JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4489] (20)

How to generate customized java 8 code from your database
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
 
Silicon Valley JUG - How to generate customized java 8 code from your database
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
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
 
Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
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
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
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
 
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...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
 
05 entity framework
05 entity framework05 entity framework
05 entity framework
 
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav TulachJDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach
JDD2015: Java Everywhere Again—with DukeScript - Jaroslav Tulach
 
Masterin Large Scale Java Script Applications
Masterin Large Scale Java Script ApplicationsMasterin Large Scale Java Script Applications
Masterin Large Scale Java Script Applications
 
How to Contribute to Apache Usergrid
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache Usergrid
 
Quick start with AngularJS
Quick start with AngularJSQuick start with AngularJS
Quick start with AngularJS
 
Java script nirvana in netbeans [con5679]
Java script nirvana in netbeans [con5679]Java script nirvana in netbeans [con5679]
Java script nirvana in netbeans [con5679]
 
Bringing DevOps to the Database
Bringing DevOps to the DatabaseBringing DevOps to the Database
Bringing DevOps to the Database
 
Escaping the yellow bubble - rewriting Domino using MongoDb and Angular
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
 
MEAN Stack Warm-up
MEAN Stack Warm-upMEAN Stack Warm-up
MEAN Stack Warm-up
 
Internship softwaretraining@ijse
Internship softwaretraining@ijseInternship softwaretraining@ijse
Internship softwaretraining@ijse
 
SharePoint 2013 Performance Analysis - Robi Vončina
SharePoint 2013 Performance Analysis - Robi VončinaSharePoint 2013 Performance Analysis - Robi Vončina
SharePoint 2013 Performance Analysis - Robi Vončina
 

Mehr von Speedment, Inc.

Mehr von Speedment, Inc. (11)

SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017
 
NYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ SpeedmentNYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ Speedment
 
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
 
DZone Java 8 Block Buster: Query Databases Using Streams
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
 
Speed-up Your Big Data Applications with Sencha and Speedment
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 & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015
 
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs
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
 
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
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 - Reactive programming for Java8
Speedment - Reactive programming for Java8Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8
 
Java days gbg online
Java days gbg onlineJava days gbg online
Java days gbg online
 
SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Kürzlich hochgeladen (20)

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

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

Hinweis der Redaktion

  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