Skip to content

Spring Boot Hello World Tutorial with Lombok and H2 Database – Quick Start for Beginners

Learn how to create a Hello World Spring Boot application using Lombok for cleaner code and the H2 in-memory database for rapid development. This step-by-step guide includes annotations, project setup, REST API, H2 console access, and more to kickstart your Spring Boot journey.

Gopi Gorantala
Gopi Gorantala
5 min read
Spring Boot Hello World Tutorial with Lombok and H2 Database – Quick Start for Beginners
Reading Progress

On This Page

Below is a deep-dive into each of the four Java classes in your “Hello World” Spring Boot project, with an eye toward SOLID design, layering, and best practices.

🔧 pom.xml - Maven dependencies

<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 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>dev.ggorantala</groupId>
  <artifactId>hello-lombok-h2</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.4</version>
    <relativePath/> 
  </parent>

  <properties>
    <java.version>17</java.version>
  </properties>

  <dependencies>
    <!-- Web starter for REST endpoints -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- JPA + Hibernate -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- In-memory H2 database -->
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>

    <!-- Lombok for getters/setters/etc. -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.28</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- Enables annotation-processing for Lombok -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <annotationProcessorPaths>
            <path>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>1.18.28</version>
            </path>
          </annotationProcessorPaths>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

📁 Project Structure

hello-world/
├── src/main/java/com/example/helloworld/
│   ├── HelloWorldApplication.java
│   ├── controller/HelloController.java
│   ├── model/User.java
│   ├── repository/UserRepository.java
│   └── data/DataLoader.java
└── src/main/resources/
    └── application.properties

🏁 Main Class

package dev.ggorantala.hellolombokh2;

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

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

Entry point of the application (the “composition root”). Lives in the bootstrap layer: it brings together all other beans and starts the Spring context.

Key Annotations

  1. @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan.
    1. @Configuration: lets you declare extra @Bean definitions if needed.
    2. @EnableAutoConfiguration: tells Spring Boot to configure your app based on classpath dependencies (e.g., JPA, Web, H2).
    3. @ComponentScan: scans your package (and subpackages) for Spring stereotypes (@Service, @Repository, @Controller, etc.).

SOLID & Patterns

  • Single Responsibility: only boots and wires up the context.
  • Open/Closed: adding new beans (services, controllers) doesn’t require modifying this class.
  • Dependency Injection: empowers the rest of your code to rely on abstractions rather than manually instantiating objects.

🌐 Simple REST Controller

package dev.ggorantala.hellolombokh2.controller;

import dev.ggorantala.hellolombokh2.model.Greeting;
import dev.ggorantala.hellolombokh2.repository.GreetingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private final GreetingRepository repo;

    @Autowired
    public GreetingController(GreetingRepository repo) {
        this.repo = repo;
    }

    @GetMapping("/hello")
    public String hello() {
        // save a new Greeting to H2 and return its message
        Greeting g = repo.save(new Greeting(null, "Hello, World!"));
        return g.getMessage();
    }
}

Web / API layer: handles HTTP requests and returns responses.

Key Annotations

  1. @RestController: shorthand for @Controller + @ResponseBody—methods return data directly in the HTTP body (no view resolution).
  2. @GetMapping("/hello"): maps GET requests for /hello to this method.
  3. @Autowired on the constructor:
    1. Constructor injection is preferred (over field/setter) for immutability and easier testing.

Method Logic

  1. Creates and saves a new Greeting entity with the text “Hello, World!”.
  2. Returns the persisted message (so you see the exact string).

SOLID & Patterns

  • Single Responsibility: only handles HTTP mapping and delegates persistence.
  • Open/Closed: to add more endpoints, create new methods—no need to touch existing mappings.
  • Dependency Inversion: depends on the GreetingRepository interface.
  • Stateless controller: no mutable fields beyond the injected repository, making it thread-safe.

🧍‍♂️Entity Class with Lombok

package dev.ggorantala.hellolombokh2.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Greeting {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String message;
}

Domain model / JPA entity in the persistence layer. Maps to a table (by default named greeting) in H2.

Key Annotations

  1. @Entity: marks this class as a managed JPA entity.
  2. @Id + @GeneratedValue: designates id as the primary key with auto-generated values.
  3. Lombok
    1. @Data: generates getters/setters, equals(), hashCode(), and a nice toString().
    2. @NoArgsConstructor / @AllArgsConstructor: boilerplate constructors for JPA and convenience.

SOLID & Patterns

  • Single Responsibility: encapsulates only the persistence fields and behavior of a “Greeting.”
  • Encapsulation: fields are private, access via methods generated by Lombok.
  • No business logic here—kept lean to respect the Layered Architecture (separate domain/persistence from service/controller).

🗃️ Repository Interface

package dev.ggorantala.hellolombokh2.repository;

import dev.ggorantala.hellolombokh2.model.Greeting;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface GreetingRepository extends JpaRepository<Greeting, Long> { }

Data access abstraction in the repository layer. Hides JPA/Hibernate boilerplate behind well-known CRUD methods.

Key Annotations & Interfaces

  1. @Repository:
    1. Marks it as a Spring bean for component scanning.
    2. Translates JPA exceptions into Spring’s DataAccessException hierarchy.
  2. Extends JpaRepository<Greeting, Long>: provides
    1. CRUD methods (save(), findAll(), findById(), delete(), etc.).
    2. Pagination and sorting out of the box.

SOLID & Patterns

  • Implements the Repository Pattern, keeping data operations isolated from business logic.
  • Dependency Inversion: higher layers (services/controllers) depend on this abstraction, not on concrete JPA code.

Annotation & Configuration Breakdown

Annotation / PropertyWhat it does
@SpringBootApplicationCombines @Configuration, @EnableAutoConfiguration, and @ComponentScan. Boots the app.
@EntityMarks a class as a JPA entity to be persisted in the database.
@IdDesignates the primary-key field of the entity.
@GeneratedValueConfigures automatic key generation strategy for the entity.
@Data (Lombok)Generates getters/setters, toString(), equals() & hashCode().
@NoArgsConstructor (Lombok)Generates a no-argument constructor.
@AllArgsConstructor (Lombok)Generates a constructor with 1 parameter per field.
@RepositoryIndicates a Spring Data repository; exception translation, etc.
@RestControllerCombines @Controller + @ResponseBody. Defines a REST endpoint.
@GetMapping("/hello")Maps HTTP GET /hello to this method.
@AutowiredInjects the GreetingRepository bean into the controller.

⚙️ application.properties

# H2 in-memory datasource
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# Show SQL in console (optional)
spring.jpa.show-sql=true

# Enable H2 console
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

🔗 H2 Console

Once you start the app and navigate to that URL, you can inspect the GREETING table and any data you’ve persisted.

How They Fit Together

  1. Startup: Spring Boot scans your package, finds @SpringBootApplication, brings up the context, and auto-configures H2, JPA, Web, and Lombok.
  2. Request: A GET to http://localhost:8080/hello hits GreetingController.hello().
  3. Persistence: The controller uses GreetingRepository to save a new Greeting to H2.
  4. Response: Controller returns the persisted message back to the client.
  5. Inspect DB: You can browse the GREETING table via the H2 console at /h2-console.

Each class plays its own role, keeps responsibilities narrow, and relies on Spring’s inversion-of-control to wire everything neatly—demonstrating strong adherence to SOLID and common design patterns.

Spring Boot TutorialsSpringspring-bootspring boot microservicesJava

Gopi Gorantala Twitter

I'm Gopi — 15+ years in Java, building Kafka and Flink platforms for banks, where one lost event is a financial discrepancy. I write javahandbook.com because the guides I needed didn't exist. Everything here is tested against a real cluster first.

Comments