Monday, April 11, 2016

Java 8: Use Smart Streams with Your Database in 2 Minutes

Streaming with Speedment

Duke and Spire Mapping Streams.

Back in the ancient 90s, we Java developers had to struggle with making our database application work properly. There was a lot of coding, debugging and tweaking. Still, the applications often blew up right in our faces to our ever increasing agony. Things gradually improved over time with better language, JDBC and framework support. I'd like to think that we developers also improved, but there are different opinions on that...

When Java 8 finally arrived, some colleges and I started an open-source project to take the whole Java/DB issue one step further by leveraging on Java 8's stream library, so that database tables could be viewed as pure Java 8 streams. Speedment was born! Wow, now we can do type-safe database applications without having to write SQL-code any more.

Speedment connects to existing databases and generate Java code. We can then use the generated code to conveniently query the database using standard Java 8 streams. With the new version 2.3 hitting the shelves just recently, we can even do parallel query streams!

Let's take some examples assuming we have the following database table defined:
 
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL,
  `firstName` varchar(45) DEFAULT NULL,
  `lastName` varchar(45) DEFAULT NULL,
  `email` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email_UNIQUE` (`email`),
  UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB;

Speedment is free for the open-source databases MySQL, PostgreSQL and MariaDB. There is also support for commercial databases, like Oracle, as an enterprise add-on feature.

Examples


Querying

Select all users with a ".com" mail address and print them:
        users.stream()
            .filter(EMAIL.endsWith(".com"))
            .forEach(System.out::println);
Select users where the first name is either "Adam" or "Cecilia" and sort them in username order, then take the first 10 of those and extract the email address and print it.
        users.stream()
            .filter(FIRST_NAME.in("Adam", "Cecilia"))
            .sorted(USERNAME.comparator())
            .limit(10)
            .map(User::getEmail)
            .forEach(System.out::println);

Creating Database Content

Create a new user and persist it in the database:
        users.newEmptyEntity()
            .setUsername("thorshammer")
            .setEmail("mastergamer@castle.com")
            .setPassword("uE8%3KwB0!")
            .persist();

Updating Database Content

Find the user with id = 10 and update the password:
        users.stream()
            .filter(ID.equal(10))
            .map(u -> u.setPassword("pA6#nLaX1Z"))
            .forEach(User::update); 

Removing Database Content

Remove the user with id = 100:
        users.stream()
            .filter(ID.equal(100))
            .forEach(User::remove);

New Cool Stuff: Parallel Queries

Do some kind of expensive operation in parallel for users with 10_000 <= id < 20_000
        users.stream()
            .parallel()
            .filter(ID.between(10_000, 20_000))
            .forEach(expensiveOperation());

Setup

Setup code for the examples above:
       final Speedment speedment = new JavapotApplication()
            .withPassword("javapot") // Replace with your real DB password
            .build();

        final Manager<User> users = speedment.managerOf(User.class);

Get Started with Speedment


Read more here on GitHub on how to get started with Speedment.

Read more about the complete set of Java 8 features including Streams.