Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. It is based on a model of Convention over Configuration and good intentions.

Introduction

This is the sixth part part of a series of posts focused on Hibernate and JPA. In my previous post we demonstrated how to write CRUD functions using interfaces in Spring Data. In this post we will look at reducing configuration with Spring Boot and writing less boilerplate code.
At the end of this post you will have familiarised yourself with Spring Boot.

Prerequisites

Project Structure

Building up on previous posts, our folder structure will remain relatively the same:

.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__tutorial/
|  |  |  |  |  |__Application.java
|  |  |  |  |  |__entity/
|  |  |  |  |  |  |__Person.java
|  |  |  |  |  |__repository/
|  |  |  |  |  |  |__PersonRepository.java
|  |  |__resources/
|  |  |  |__application.properties
|  |  |  |__dbChangelog.xml
|  |  |  |__log4j2.properties
|__pom.xml

Setting up Dependencies

To set up a Spring Boot project we need the following dependencies

  • spring-boot-starter

Modify the pom.xml file by making the following changes:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.2.RELEASE</version>
  <relativePath />
</parent>

<properties>
  <hibernate.version>5.2.6.Final</hibernate.version><!-- Override version 5.0 used by Spring Boot -->
  <java.version>1.8</java.version>
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
      <exclusion><!-- Hibernate EntityManager was merged into Hibermate core in 5.2 -->
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
      </exclusion>
      <exclusion>
        <groupId>org.apache.tomcat</groupId><!-- We will be using HikariCP pooling library -->
        <artifactId>tomcat-jdbc</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

Wow! That’s a lot of changes. But that will be all for our POM.xml.

Naming Strategy

Hibernate 5 deprecated the legacy NamingStrategy in favour of ImplicitNamingStrategy and PhysicalNamingStrategy. With the release of Spring Boot 1.4, a new SpringPhysicalNamingStrategy is auto configured to align with Hibernate 5.
Part of the mapping of an object model to the relational database is mapping names from the object model to the corresponding database names. The SpringPhysicalNamingStrategy uses snake case for the database names. In this regard we will modify our Liquibase Changelog file.

file: src/main/resources/dbChangelog.xml:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog 
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 
    http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
  <property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle,mssql"/>

  <changeSet id="0" author="julius" dbms="h2,postgresql,oracle">
    <createSequence sequenceName="hibernate_sequence" startValue="1" incrementBy="1"/>
  </changeSet>
		
  <changeSet id="1" author="julius">
    <comment>Create Person table</comment>
    <createTable tableName="person">
      <column name="id" type="bigint" autoIncrement="${autoIncrement}">
        <constraints primaryKey="true" nullable="false" />
      </column>
      <column name="first_name" type="varchar(255)"/>
      <column name="last_name" type="varchar(255)"/>
      <column name="date_of_birth" type="date"/>
      <column name="created_date" type="timestamp"/>
      <column name="modified_date" type="timestamp"/>
    </createTable>
  </changeSet>
</databaseChangeLog>

Plumbing

We now made a few minor changes to get Spring Boot up and running.

file: src/main/resources/application.properties:

spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.javax.persistence.provider=org.hibernate.jpa.HibernatePersistenceProvider
spring.jpa.properties.hibernate.hikari.dataSourceClassName=org.h2.jdbcx.JdbcDataSource
spring.jpa.properties.hibernate.hikari.dataSource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MVCC=true
spring.jpa.properties.hibernate.hikari.dataSource.user=sa
spring.jpa.properties.hibernate.hikari.dataSource.password=
spring.jpa.properties.hibernate.hikari.minimumIdle=5
spring.jpa.properties.hibernate.hikari.maximumPoolSize=10
spring.jpa.properties.hibernate.hikari.idleTimeout=30000
spring.jpa.properties.hibernate.connection.handling_mode=delayed_acquisition_and_hold
spring.jpa.properties.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider

liquibase.change-log=classpath:/dbChangelog.xml
liquibase.check-change-log-location=true
liquibase.contexts=test
liquibase.drop-first=true
liquibase.enabled=true

Spring Boot

Spring Boot is all about reducing the amount of boilerplate code you have to write.
Remove:

file: src/main/java/com/tutorial/Application.java:

@Configuration
@EnableJpaRepositories
@EnableTransactionManagement
@PropertySource("classpath:application.properties")

replace with:

@SpringBootApplication

Next remove all beans from the Application class and we end up with this:

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(Application.class, args);
		
    PersonRepository repository = ctx.getBean(PersonRepository.class);
    Person person = new Person();
    person.setFirstName("Julius");
    person.setLastName("Krah");
    person.setCreatedDate(LocalDateTime.now());
    person.setDateOfBirth(LocalDate.of(1990, Month.APRIL, 4));

    // Create person
    repository.save(person);

    // Hibernate generates id of 1
    Optional<Person> p = repository.findOne(1L);

    p.ifPresent(consumer -> {
      consumer.setModifiedDate(LocalDateTime.now());
      consumer.setFirstName("Abeiku");
    });
    // Update person record
    repository.save(p.get());

    p = Optional.empty();

    // Read updated record
    p = repository.findOne(1L);
    p.ifPresent(consumer -> {
      System.out.format("Person updated: %s", consumer);
    });
    // Delete person
    repository.delete(p.get());

    p = Optional.empty();

    p = repository.findOne(1L);
  }
}

That’s it.

Conclusion

In this post we did a rewrite of our previous articles in the series to use Spring Boot. We also saw how easy it is to configure a Spring Boot project. As usual you can find the full example to this guide in the github repository. Until the next post, keep doing cool things :+1:.