Skip to content

Data, Spring Boot and H2

Estimated time to read: 5 minutes

H2 Database

H2 is an OSS database written in Java. For more information, see H2

It is an 'in-memory' database, meaning that data is stored in memory and is not committed to the disk thus data will not persist between runs.

H2 is not recommended for production environment, however, it is a valid use for POCs, development environments or projects that require a simple, ephemeral, database.

H2 can be easily integrated with Spring. H2 also provides an administrative tool, the H2 Console which can be used in-browser to administer the database.

Dependency

H2 can be included as a dependency in the Maven POM or Gradle build file. Since H2 is being added as a dependency to the project, automatic configuration will inform Spring Boot that the project will be connecting to a H2 database and automatically configures H2 related properties such as the database URL, username, password, etc.

H2 Defaults
spring.datasource.url=jbdc:h2:mem:testdb // Default datasource name
spring.datasource.driverClassName=org.h2.Driver // Driver class
spring.datasource.username=sa // Default username
spring.datasource.password= // No default password
spring.h2.console.enabled=false // Console disabled
application.properties
// Overrides
spring.h2.console.enabled=true // Enable the console
spring.h2.console.path=/h2 // Set the path of the console to /h2
spring.datasource.url=jdbc:h2:mem:bugtracker // Set the datasource name to 'bugtracker'

ORM with JPA

Object-Relational Mapping (ORM) with the Java Persistance API (JPA).

There are several layers of abstraction to explore with ORM and the JPA.

At the lowest level is the Data Store, this could be a SQL server, a flat file or any other form of data.

Above that is the Java Database Connectivity API (JDBC). The JDBC is a Java API to connect to and execute queries against a database.

Java Persistence API (JPA) is an abstraction on top of JDBC that makes it easy to map Java objects to relational databases and vice versa.

JPA is a specification and does nothing on its own, as it is a set of empty methods and collection of interfaces that only describe Java persistence methodologies. In order to be fully functional, JPA requires an implementation also known as an instance provider. Spring uses Hibernate as it the instance provider

Spring Data JPA provides repository support for the JPA. It assists in the development of applications that need access to JPA data sources.

flowchart BT
    A{Data Source}
    B[Java Database Connectivity]
    C[Java Persistence API]
    D[Spring Data JPA]

    A <--> B
    B --- C
    C --- D

The Spring Boot Starter spring-boot-starer-dta-jpa can be used to automatically include the following dependencies:

  • Hibernate
  • A popular JPA implementation
  • Spring Data JPA
  • Makes it easy to implement JPA repositories
  • Spring ORM
  • The core ORM support for the Spring Framework

Entities

Entities are objects that are stored within a database and also have the ability to be mapped to a database.

Entities are defined by the @Entity annotation. This is used to qualify the POJO as an Entity. The @Id annotation can also be used to define the entities primary key.

Traditionally, JPA entity classes are specified in a a persistence.xml file, however with Spring Boot this is no longer neccessary as entity scanning is used. By default, all packages below the main application class, annotated with either @SpringBootApplication or @EnableAllConfiguration are searched.

Any classes that are annotated with @Entity are included and made available to the application.

H2 Integration

Trackzilla has three domain entities that represent the data captured by the system. These are:

Application.java
// ...
@Entity // Indicates this is a JPA entity, it assumes that this entity will be mapped to a table named 'Application'.
public class Application { // This domain entity represents the Application that a request will be tracked against.
    @Id // The @Id annotation sets this as an objects ID / primary key in the data source
    @GeneratedValue(strategy = GenerationType.AUTO) // The @GeneratedValue annotation, with the given parameters, sets the value of this field to be auto generated and declared in the data source
    @Column(name="application_id") // The @Column annotation is used to declare the column name in the datasource
    private Integer id;

    @Column(name="app_name", nullable = false)
    private String name;

    @Column(length = 2000)
    private String description;
    private String owner;

    // ...
}
Ticket.java
// ... 

@Entity
public class Ticket {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String title;
    private String description;

    @ManyToOne // The @ManyToOne annotation creates a bi-directional relationship between tables
    @JoinColumn(name = "application_id")
    private Application application;

    @ManyToOne
    @JoinTable(name ="ticket_release", joinColumns = @JoinColumn(name = "ticket_fk"), inverseJoinColumns = @JoinColumn(name = "release_fk"))
    private Release release;

    // ...
}
Release.java
// ...

@Entity
public class Release {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String releaseDate;
    private String description;

    public Release() {
    }

    public Release(Integer id, String description, String releaseDate){
        this.id = id;
        this.releaseDate = releaseDate;
        this.description = description;
    }

    // ...
}

Data Repository Abstraction

The Spring Data Repository abstraction greatly reduces the need to have boilerplate code to implement data access for most databases.

Following the example above, there are should three Repository abstractions, one per entity, to enable this.

The Spring Data JPA repository abstraction allows access to data be creating JPA queries automatically from a method name.

Note that the abstraction is an interface, however, there is no implementation provided. This is because Spring Boot automatically provides the implementation on the developers behalf.

ApplicationRepository.java
package io.entityfour.repository;

import com.pluralsight.entity.Application;
import org.springframework.data.repository.CrudRepository;

// Create an interface for the entityRepo, it extends CrudRepository<EntityName>, <EntityValueType>
public interface ApplicationRepository extends CrudRepository<Application, Long> {
}

Usage

MainApplication.app
// ...
@SpringBootApplication
public class FundamentalsApplication {

 private static final Logger log = LoggerFactory.getLogger(FundamentalsApplication.class);

 public static void main(String[] args) {
  SpringApplication.run(FundamentalsApplication.class, args);
 }

 @Bean
    // Type CommandLineRunner makes the following a command line based application
    // It accepts the ApplicationRepository as a parameter
 public CommandLineRunner demo(ApplicationRepository repository) {
  return (args) -> {

            // Using the ApplicationRepository abstraction / interface. Use .save() to save new data to the database
   repository.save(new Application("Trackzilla","kesha.williams","Application for tracking bugs."));
   repository.save(new Application("Expenses","mary.jones","Application to track expense reports."));
   repository.save(new Application("Notifications","karen.kane","Application to send alerts and notifications to users."));

   for (Application application : repository.findAll()) { // Using a for loop, get all application objects and log them out
    log.info("The application is: " + application.toString());
   }
  };
 }
}

H2 Console

Login

The H2 Console, when enabled in application.properties, can be accessed via http://127.0.0.1:8080/h2.

The administrative console will be presented within the web browser.

The requested connection details must match those of the H2 configuration specified in application.properties. Once these have been entered, a connection to the database can be established.

Database Browser

Once connected, the web browser will display H2's database browser.

The pane on the left side of the console shows the current database structure, this includes the entities defined within the application, as well as the database schema information.

Selecting one of the entities in the left pane will generate a SQL query that can be used to query the database. Other SQL commands can be passed to manipulate data if needed.