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

Table of Contents

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

Gopi is an Engineering Manager with over 14 years of extensive expertise in Java-based applications. He resides in Europe and specializes in designing and scaling high-performance applications.

Comments


Related Posts

Members Public

How to fix port 8080 already in use error on Windows and macOS

Getting the “Web server failed to start. Port 8080 was already in use” error? Learn how to identify and kill the process blocking port 8080 on Windows and macOS using simple terminal commands. Fix server startup issues fast and keep your development running smoothly.

How to fix port 8080 already in use error on Windows and macOS
Members Public

Spring vs. Spring Boot: Key Differences Developers Must Know

Spring or Spring Boot? One gives you full control, the other gets you up and running fast. If you're building Java apps, knowing the difference isn't optional—it’s critical. Here’s the breakdown every dev should read.

Spring vs. Spring Boot: Key Differences Developers Must Know
Members Public

NoSuchBeanDefinitionException: The Most Common Spring Bean Error

Learn how to fix NoSuchBeanDefinitionException in Spring Boot with clear examples and best practices for dependency injection, package scanning, and bean registration.

NoSuchBeanDefinitionException for a missing bean in the ApplicationContext.