Java has been a purely imperative language for the majority of its existence. With the release of Java 8 back in 2014, a more declarative approach was introduced to the language in the form of Streams.
I love Streams, they’re one of my favourite features to be released as a part of a programming language in general. This article series is a guide on how to use Streams to interact with a relational database of your choice, but if you’re looking for a tutorial that focuses specifically on Java Streams, make sure to check out this guide.
Streams vs SQL - more similar than you’d think
Believe it or not Java Streams and SQL are quite similar. “How?” you might ask. Well take a look at the following table:
SQL |
JAVA STREAM |
FROM |
stream() |
COUNT |
count() |
LIMIT |
limit() |
SELECT |
map() |
WHERE |
filter() (before collecting) |
HAVING |
filter() (after collecting) |
JOIN |
flatmap() |
UNION |
concat(s0, s1).distinct() |
ORDER BY |
sorted() |
OFFSET |
skip() |
GROUP BY |
collect(groupingBY()) |
Most SQL operations have a cousin in the Java Stream world. Due to this similarity, it is very much possible to express SQL statements as standard Java Streams. Speedmentuses this knowledge to create a fast and type-safe environment for database application development.
In this first part of my “Intro to Speedment” guide we will be taking a look at how to translate your database into Java form and create a simple query.
Preparing the database
Before we can do anything regarding Speedment, we need to have a database ready. For this guide we'll be using a MySQL sample database called Sakila. It is a database with films and actors, intended to provide a standard schema that can be used for demo applications. You’re free to use a different database if you’d like, but do note that your Java representation of the database will be different from the one in this guide.
The Speedment Tool
A lot of ORMs require you to manually write your own language-specific representation of the database. Speedment comes with a tool that handles this for you, meaning you don’t have to write a single LOC in order to translate your database to Java.
Head over to the Speedment Initializer where you’ll be able to download the Speedment Tool and all of the additional dependencies needed to use the Speedment ORM. I’ve included the settings used for this guide:
If your setup is different, make sure those differences are reflected in the Initializer settings.
Once you’re done configuring the project, click the Download button and unpack the downloaded zip-file. To launch the Speedment Tool, execute the following command from a terminal:
mvn speedment:tool
Connecting to your database
If this is your first time running the Speedment Tool, you’ll be asked to connect to your database. We’re running the vanilla MySQL Sakila sample database on our local machine, so the login information would look like this:
Once you’ve filled in the required fields, click the Connect button.
Generating your database representation
If the login information you’ve provided was correct, you will be presented with the following screen:
The user interface for the Speedment Tool is quite easy to understand. On the left-hand side there is a tree structure representing your database metadata and on the right-hand side contains options which change depending on what you’re currently looking at in the metadata. Everything you change in these options will be reflected in the final Java representation of your database.
For the purposes of this guide we haven’t changed anything in the Tool, but feel free to play around with the different settings. Once you’re satisfied with the settings, click the Generate button in the top left corner of the Tool. This will generate the Java representation of your database.
Generated objects
If you’ve done everything correctly up to this point, you should notice a bunch of generated files in your src folder. There are way too many files so we can’t cover what every single one does, but we will go over the most important ones needed for you to get started with Speedment.
Entities
For every table in your database, an entity interface gets generated. For example, we have a table called actor in our database, so there is an interface called Actor. Entity interfaces are used to retrieve query results and provide information to Speedment during persistence.
Managers
For every entity that exists, there is a manager inteface that accompanies it. For example, we have an entity called Actor, so there is an interface called ActorManager that goes with it. Managers handle all CRUD operations for a specific entity.
Application
Every Speedment project comes with an Application interface. An Application interface allows you to access all of the different components that Speedment offers. We will be using our generated Application soon to get access to a Manager.
Entry Point
The EntryPoint class is the main class of your Speedment project. You can look at it as a convenience class to get you started faster, meaning you’re not actually required to use it if you want to create a main class of your own.
Authenticating Speedment
We’ll wrap up the first part of our guide by showing you how to execute a simple query with Speedment. Remember that EntryPoint class we talked about in the previous chapter? On its own it’s pretty useless, but we can use it to execute our query. However, before we can execute any query, we need to allow Speedment to use our database.
When you generated the project with the Speedment Tool, some of the login information, such as the username and database name, was stored for convenience. One thing that Speedment doesn’t store is the password, which you must provide yourself.
In the generated EntryPoint class, our Application instance gets built via an ApplicationBuilder. The ApplicationBuilder lets us configure a bunch of options in our Application. One of the things we can configure is the password our Application uses to connect to the database. This is done by calling ApplicationBuilder::withPassword.
For our Sakila database, the new ApplicationBuilder block would look like this:
final SakilaApplication application = new SakilaApplicationBuilder()
.withPassword("sakila")
.build();
If the password is correct, running the application should result in no errors and immediately terminate.
Executing a simple query
Now that we’ve authorized Speedment to use our database we can execute a simple query to see that everything is working. In order to execute a query with Speedment, we need to get a hold of a Manager instance for the Entity we are trying to query.
We’ve mentioned how we need an Application instance to access our Managers. Luckily this is already handled for us in the generated EntryPoint, so all we have to do now is access the Manager itself. This is done by invoking Application::getOrThrow.
The Actor Entity and Manager were used as examples throughout the whole guide, so we will continue in the same fashion. To access and store an instance of our Actor Manager we can add the following to our EntryPoint:
final ActorManager actors = application.getOrThrow(ActorManager.class)
As we’ve already stated at the beginning of the guide, Speedment uses standard Java Streams to create queries, meaning that anything you can do with the Streams API, you can do with Speedment. The second part of our guide will focus entirely on querying with Speedment, but for now we will show you a really simple query to get you started. For every actor that’s in our database we want to print their id, first name and last name. With the Stream API that can be done like so:
actors.stream().forEach(actor -> System.out.printf(
"ID: %d, First name: %s, Last name: %s%n",
actor.getActorId(),
actor.getFirstName(),
actor.getLastName()
));
If you add this block of code to your EntryPoint and run it, you should get an output similar to this one:
ID: 1, First name: PENELOPE, Last name: GUINESS
ID: 2, First name: NICK, Last name: WAHLBERG
ID: 3, First name: ED, Last name: CHASE
ID: 4, First name: JENNIFER, Last name: DAVIS
ID: 5, First name: JOHNNY, Last name: LOLLOBRIGIDA
ID: 6, First name: BETTE, Last name: NICHOLSON
ID: 7, First name: GRACE, Last name: MOSTEL
ID: 8, First name: MATTHEW, Last name: JOHANSSON
ID: 9, First name: JOE, Last name: SWANK
ID: 10, First name: CHRISTIAN, Last name: GABLE
------------------- TRUNCATED -------------------
Summary
By working with SQL directly inside of our Java applications, we lose all of the type-safety benefits that Java provides us. With Speedment’s easy-to-use Stream API, we avoid these problems altogether.
I hope you’ve enjoyed the first part of my introduction to Speedment. In the following weeks we’ll cover the Stream API in depth, so make sure to watch out for that.
Resources
About
Mislav Miličević
Mislav Miličević started to develop at the age of 11. When he was 14 years old he began making custom client and server modifications for the game Minecraft. Today he is an experienced Java developer and blogger working as a software developer at Speedment.