H2 Database
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
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
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
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.
JDBC url should be the url from your application.properties defined url. student_db is my database name. Lets try to connect.
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.
Lets add some data for this database from postman
We can see that the data is now inserted in H2 database console
Lets update the data for id 1
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