H2 Database

Laishram Trinity
6 min readJun 1, 2024

--

H2 database is an inbuilt memory for springboot framework , it’s useful for testing purpose as it’s not connected to any database. The data in the H2 database will reatined as long as the server is up. Once the server is down all the data will be lost.

To see the data we have to used a console of H2 its a basic UI. The hibernate will work as expected in H2 database also.

H2 database has to be added externally as an dependency

I have used Lombok so, that we can used annotation for getter setter and constructors. We can add the lombok dependency while initializing the project or from mvn repository.

Project Folder Structure

In this project we will perform a CRUD operation for a student entity.

Now, lets see how the pom.xml will look like

Here we can see that lombok and H2 database were added.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.trinity</groupId>
<artifactId>H2DataBase</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>H2DataBase</name>
<description>H2 Database</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>

application.properties

application.properties

server port can be defined by yourself.

spring.h2.console.enabled=true 
it's stating that the console for h2 should be enable
spring.datasource.url=jdbc:h2:mem:student_db
url has to be set externally and comes under jdbc student_db is the database name

username is sa and password is password by default. And the dialect is H2Dialect.

appication.properties

spring.application.name=H2DataBase

server.port = 8082

# H2 Database
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:student_db
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

Lets see the enity class of Student

package com.trinity.H2DataBase.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

@Getter
@Setter
@AllArgsConstructor
@Data
@NoArgsConstructor
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NonNull
private Long id;
@NonNull
private String name;
@NonNull
private String address;
@NonNull
private Long rollNo;
}

Observe the lombok has been imported, and getter , setter, constructors were implemented by simply putting the annotation. In this class I have used the @NonNull so, that validation will be there. The field must be filled according to the provided dattypes it should not be empty.

For repository , I have named it as StudentRepository

package com.trinity.H2DataBase.repository;

import com.trinity.H2DataBase.entity.Student;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends CrudRepository<Student,Long> {

}

The repository should be an interface class. @Repository annotation is used to tell the hibernate that this interface is for the repository and this interface is again extends the CrudRepository , we can used the JPARepo from jakarta also. The datatype should be of type Student class and the @Id from the Student class which is the Long datatype again.

For the service package again we have to write a service interface and again implemetation of it.

Below is the code for StudentService

package com.trinity.H2DataBase.service;

import com.trinity.H2DataBase.entity.Student;

import java.util.List;

public interface StudentService {
Student saveStudent(Student student);
List<Student> fetchStudentList();
Student updateStudent(Student student , Long id);
void deleteStudentById(Long id);
}

I have declared four methods for save, fetching,update and delete.

For fetching it needs to return in List as it’s fetching all the available students detail.

Lets see the implementation of the service

package com.trinity.H2DataBase.service;


import com.trinity.H2DataBase.entity.Student;
import com.trinity.H2DataBase.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


@Service
public class StudentServiceImpl implements StudentService {

@Autowired
StudentRepository studentRepository;

@Override
public Student saveStudent(Student student) {
return studentRepository.save(student);
}

@Override
public List<Student> fetchStudentList() {
// Retrieve the Iterable<Student> from the repository
Iterable<Student> studentIterable = studentRepository.findAll();

// Create a new ArrayList<Student> to store the fetched students
List<Student> studentList = new ArrayList<>();

// Iterate over the Iterable<Student>
studentIterable.forEach(studentList :: add);
return studentList;
}

@Override
public Student updateStudent(Student student, Long id) {
Optional<Student> existingStudent = studentRepository.findById(id);
if (!existingStudent.isPresent()){
throw new RuntimeException("Id "+id+" is not found");
}

Student updatedStudent = new Student();
updatedStudent.setName(student.getName());
updatedStudent.setAddress(student.getAddress());
updatedStudent.setRollNo(student.getRollNo());
updatedStudent.setId(student.getId());
return studentRepository.save(updatedStudent);
}

@Override
public void deleteStudentById(Long id) {
studentRepository.deleteById(id);
}
}

I have used @Service annotation to tell the hibernate that this is the service class. The service will communicate with the repository for that it needs to inject the repository class so, I have used @Autowired annotation and inject the StudentRepository and create an object of it.

Lets see the controller class

package com.trinity.H2DataBase.controller;


import com.trinity.H2DataBase.entity.Student;
import com.trinity.H2DataBase.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("students")
public class StudentController {
@Autowired
private StudentService studentService;

// Save student
@PostMapping("/save")
public Student saveStudent(
@Validated @RequestBody Student student)
{
return studentService.saveStudent(student);
}

// Read student
@GetMapping("/get")
public List<Student> fetchStudentList()
{
return studentService.fetchStudentList();
}

// Update student
@PutMapping("/update/{id}")
public Student updateStudent(@RequestBody Student student,
@PathVariable("id") Long id)
{
return studentService.updateStudent(
student, id);
}

// Delete student
@DeleteMapping("/delete/{id}")
public String deleteStudentById(@PathVariable("id")
Long id)
{
studentService.deleteStudentById(
id);
return "Student details deleted Successfully";
}
}

@RestController annotation tells the hibernate that this is the controller class and used @RequestMapping to give the API starting name. Controller will communicate with the Service class so, I have autowired the StudentService.

Main class

package com.trinity.H2DataBase;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class H2DataBaseApplication {

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

}

Lets start the server

server is up and running on port number 8082 for H2DatabaseApplication

Lets see the console of H2 Database

write this http://localhost:8082/h2-console or copy paste at your browser then a console of H2 Database will be opened.

H2 Database UI console

JDBC url should be the url from your application.properties defined url. student_db is my database name. Lets try to connect.

Testing for connection

Password will be password by default and it’s also defined in application.properties write password at password textarea and click on the test connection.

Lets open the database. ReType the console password and click on connect.

On successfull connection
The table is empty.

Lets add some data for this database from postman

Id is auto generated strategy

We can see that the data is now inserted in H2 database console

Lets update the data for id 1

Student details updated for Id 1
Updated details
Three student details were added

Lets fetch all

Lets delete student with id 3

Check in database H2

Lets shut the server and see

Again, lets restart the server

Lets see the H2 database console

It’s empty again

--

--