In the previous article, 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 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:
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:
<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 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:
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:
spring.datasource.url=jdbc:h2:file:/opt/jpadb
Check out the H2 documentation 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:
Book.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:
BookRepository.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:
Application.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:
$ ./gradlew bootRun
For Maven, you can run the application by typing:
$ ./mvnw spring-boot:run
Once the application is started, you should see the following output printed on the console:
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 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 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 guide.
✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.