# Spring Data JPA with H2 DataBase and Spring Boot

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Oct 2, 2019, updated Sep 25, 2022. Topics: Spring Boot, Spring Data JPA.
Canonical URL: https://attacomsian.com/blog/spring-data-jpa-h2-database

> Learn how to use Spring Data JPA with H2 in-memory database in a Spring Boot application for storing, accessing, updating, and deleting entities.

In the [previous article](https://attacomsian.com/blog/getting-started-spring-data-jpa), I wrote about Spring Data JPA and how to use it in the Spring Boot application. We also discussed compelling features that make Spring Data JPA a powerful tool.

In this article, you'll learn **how to use Spring Data JPA with the H2 database in a Spring Boot** project for storing, accessing, updating, and deleting data (CRUD operations).

[H2](https://www.h2database.com/html/main.html) is an open-source **in-memory SQL database written in Java**. It can be embedded in Java applications or used as a standalone database in client-server mode. An in-memory database is created when the application starts up and is destroyed when the application shuts down.

## Dependencies

We only need `h2` and `spring-data-starter-data-jpa` dependencies to use the H2 database with Spring Data JPA. For a Gradle project, add the following dependencies to your `build.gradle` file:

```groovy
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
```

If you are using Maven, include the following dependencies to your `pom.xml` file:

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
```

Alternatively, you can use [Spring Initializr](https://start.spring.io/) web tool to bootstrap a new Spring Boot application with the above dependencies.

## Configure H2 Database

Spring Boot **automatically configures the data source when it detects the H2 database** dependency in the classpath. You do not need to do anything unless you want to customize the default configuration.

By default, Spring Boot configures the application to connect to an in-memory store with the **sa** username and an **empty** password. You can override these parameters by adding the following properties to your `application.properties` or `application.yml` file:

```properties
spring.datasource.url=jdbc:h2:mem:jpadb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=mypass
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
```

Since the in-memory database is removed when the application shuts down, we will lose the data when the application restarts.

To prevent this default behavior, we can switch to file-based storage by updating the `spring.datasource.url` property like below:

```properties
spring.datasource.url=jdbc:h2:file:/opt/jpadb
```

Check out the [H2 documentation](http://www.h2database.com/html/features.html#connection_modes) for more connections mode. For this example, **we will use the in-memory mode**.

## Create an Entity

Let us create a simple entity class for storing `Book` objects:

<p class="file-desc"><span>Book.java</span></p>

```java
package com.attacomsian.jpa.domains;

import javax.persistence.*;

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String title;
    @Column(unique = true)
    private String isbn;

    public Book() {
    }

    public Book(String title, String isbn) {
        this.title = title;
        this.isbn = isbn;
    }

    // getters and setters removed for brevity
}
```

The above `Book` class is very similar to what we defined in the previous article. The class is annotated with `@Entity`, indicating that it is a JPA entity.

The `id` attribute is annotated with both `@Id` and `@GeneratedValue` annotations. This means that it is the object's auto-generated primary key.

The `@Column` annotation is used to specify the mapped column for a persistent property or field in the database. We set the `unique` property to `true` to indicate that this column is a unique key. In short, the `isbn` property must be unique for all books.

## Create a Repository

Let us create a repository interface for our `Book` entity:

<p class="file-desc"><span>BookRepository.java</span></p>

```java
package com.attacomsian.jpa.repositories;

import com.attacomsian.jpa.domains.Book;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface BookRepository extends CrudRepository<Book, Long> {

    Book findByIsbn(String isbn);

    List<Book> findByTitleContaining(String title);
}
```

The `BookRepository` interface is very much self-explanatory. We are extending the Spring Data JPA `CrudRepository` interface to inherit several methods for manipulating `Book` entities.

We also defined two additional methods to get a `Book` entity by its ISBN value and all books that contain a specific keyword in their title value.

## Create an Application Class

The next step is to create the main application class for our [Spring Boot console application](https://attacomsian.com/blog/spring-boot-console-application):

<p class="file-desc"><span>Application.java</span></p>

```java
package com.attacomsian.jpa;

import com.attacomsian.jpa.domains.Book;
import com.attacomsian.jpa.repositories.BookRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

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

    @Bean
    public CommandLineRunner bookDemo(BookRepository bookRepository) {
        return (args) -> {

            // create books
            bookRepository.save(new Book("Thinking in Java", "0136597238"));
            bookRepository.save(new Book("Beginning Java 2", "1861002238"));
            bookRepository.save(new Book("Java Gently", "0201342979"));
            bookRepository.save(new Book("Java 2 Platform Unleashed", "0672316315"));

            // fetch all books
            System.out.println("Books found with findAll():");
            System.out.println("---------------------------");
            for (Book book : bookRepository.findAll()) {
                System.out.println(book.toString());
            }
            System.out.println();

            // fetch book by id
            Book book = bookRepository.findById(1L).get();
            System.out.println("Book found with findById(1L):");
            System.out.println("-----------------------------");
            System.out.println(book.toString());
            System.out.println();

            // fetch book by ISBN
            Book bookWithIBSN = bookRepository.findByIsbn("0201342979");
            System.out.println("Book found with findByEmail('0201342979'):");
            System.out.println("------------------------------------------");
            System.out.println(bookWithIBSN.toString());
            System.out.println();

            // fetch all books that contain the keyword `java`
            System.out.println("Books that contain keyword 'java':");
            System.out.println("----------------------------------");
            for (Book b : bookRepository.findByTitleContaining("java")) {
                System.out.println(b.toString());
            }
            System.out.println();

            // update book title
            Book bookUpdate = bookRepository.findById(2L).get();
            bookUpdate.setTitle("Java Gently 2nd Edition");
            bookRepository.save(bookUpdate);
            System.out.println("Update book title:");
            System.out.println("------------------");
            System.out.println(bookUpdate.toString());
            System.out.println();

            // total books in DB
            System.out.println("Total books in DB:");
            System.out.println("------------------");
            System.out.println(bookRepository.count());
            System.out.println();

            // delete all books
            bookRepository.deleteAll();
        };
    }
}
```

The above main application class demonstrates how to use the `BookRepository` interface for creating, accessing, updating, and deleting `Book` entities.

## Run the Application

You can easily run the application from the command line by using Gradle or Maven build tools. For Gradle, run the application by executing the following command:

```bash
$ ./gradlew bootRun
```

For Maven, you can run the application by typing:

```bash
$ ./mvnw spring-boot:run
```

Once the application is started, you should see the following output printed on the console:

```plaintext
Books found with findAll():
---------------------------
Book{id=1, title='Thinking in Java', isbn='0136597238'}
Book{id=2, title='Beginning Java 2', isbn='1861002238'}
Book{id=3, title='Java Gently', isbn='0201342979'}
Book{id=4, title='Java 2 Platform Unleashed', isbn='0672316315'}

Book found with findById(1L):
-----------------------------
Book{id=1, title='Thinking in Java', isbn='0136597238'}

Book found with findByEmail('0201342979'):
------------------------------------------
Book{id=3, title='Java Gently', isbn='0201342979'}

Books that contain the keyword 'java':
----------------------------------

Update book title:
------------------
Book{id=2, title='Java Gently 2nd Edition', isbn='1861002238'}

Total books in DB:
------------------
4
```

> **Source code:** Download the complete source code from [GitHub](https://github.com/attacomsian/code-examples/tree/master/spring-data-jpa/jpa-h2) available under MIT license.

## Conclusion

That's all folks for today. In this article, you have learned how to use Spring Data JPA with H2 in-memory database for storing and retrieving books in a Spring Boot application.

Check out the [getting started with Spring Data JPA](https://attacomsian.com/blog/getting-started-spring-data-jpa) guide to learn more about its core features and how to configure different data sources.

If you are using MySQL with Spring Data JPA, check out [Accessing Data with Spring Data JPA and MySQL](https://attacomsian.com/blog/accessing-data-spring-data-jpa-mysql) guide.
