📚 មេរៀន Java · Spring Boot

Lombok ជាមួយ Spring Boot

រៀនប្រើ Lombok annotations ដើម្បីកាត់បន្ថយ boilerplate code នៅក្នុង Spring Boot project

01

Lombok គឺជាអ្វី?

Lombok គឺជា Java library ដែលប្រើ annotation processing ដើម្បីបង្កើត code ដោយស្វ័យប្រវត្តិ ដូចជា getters, setters, constructors, equals, hashCode, toString ជាដើម — ដោយមិនចាំបាច់សរសេរដោយដៃ។

នៅក្នុង Spring Boot project ធម្មតា, យើងតែងសរសេរ POJO / Entity class ដែលមាន fields ច្រើន ហើយ IDE generate ចេញ getter/setter ដ៏វែង។ Lombok ជួយកាត់បន្ថយ code ទាំងនោះដោយគ្រាន់តែដាក់ annotation ងាយៗ។

@Getter @Setter @Data @Builder @AllArgsConstructor @Slf4j @RequiredArgsConstructor
02

ការដំឡើង (Setup)

1

បន្ថែម Dependency ក្នុង pom.xml

បើប្រើ Maven, បន្ថែម Lombok dependency:

pom.xml
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>
2

ឬប្រើ Gradle

build.gradle
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
3

ដំឡើង IntelliJ IDEA Plugin

ចូល Settings → Plugins → ស្វែងរក "Lombok" → Install → Restart IDE

ហើយបើក Settings → Build → Compiler → Annotation Processors → Enable annotation processing

03

Annotations សំខាន់ៗ

@Getter / @Setter
បង្កើត getter និង setter methods ដោយស្វ័យប្រវត្តិសម្រាប់ fields ទាំងអស់
@Data
រួមបញ្ចូល @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor
@Builder
បង្កើត Builder pattern ដើម្បី construct object ដោយងាយ
@NoArgsConstructor
បង្កើត constructor ដែលគ្មាន parameter
@AllArgsConstructor
បង្កើត constructor ដែលមាន parameter គ្រប់ fields
@RequiredArgsConstructor
បង្កើត constructor សម្រាប់ final fields ឬ @NonNull fields
@ToString
Override toString() method ដោយស្វ័យប្រវត្តិ
@Slf4j
Inject logger variable log ដើម្បីប្រើ logging ភ្លាមៗ
04

ឧទាហរណ៍: @Data (មុន និង ក្រោយ)

ក្រោយប្រើ @Data code ខ្លីណាស់ ប្រៀបទៅនឹងការសរសេរដោយដៃ:

❌ មិនប្រើ Lombok (វែង)
public class User {
  private Long id;
  private String name;
  private String email;

  public Long getId() {
    return id;
  }
  public void setId(Long id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String n){
    this.name = n;
  }
  // ... getter/setter ជាច្រើនទៀត
  public String toString() {...}
  public boolean equals(...) {...}
}
✅ ប្រើ Lombok (ខ្លី)
@Data
public class User {
  private Long id;
  private String name;
  private String email;
}

// Lombok generate ជូន:
// ✓ getId(), setId()
// ✓ getName(), setName()
// ✓ getEmail(), setEmail()
// ✓ toString()
// ✓ equals() & hashCode()
// ✓ constructor()
05

ឧទាហរណ៍: JPA Entity Class

ការប្រើ Lombok ជាមួយ JPA Entity — ត្រូវបន្ថែម @NoArgsConstructor ផងដែរ ព្រោះ JPA ត្រូវការ default constructor:

Product.java — JPA Entity
package com.example.demo.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name = "products")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    private String description;

    @Column(nullable = false)
    private Double price;

    private Integer stock;
}
⚠️ ចំណាំ: ពេលប្រើ @Data ជាមួយ JPA Entity ត្រូវប្រយ័ត្ន! ខ្លះណែនាំប្រើ @Getter @Setter @ToString ដាច់ដោយឡែក ដើម្បីជៀសវាង issue ជាមួយ Hibernate lazy loading។
06

ឧទាហរណ៍: DTO Class

DTO (Data Transfer Object) ប្រើ Lombok បានប្រកបដោយសុវត្ថិភាព:

ProductDto.java
package com.example.demo.dto;

import lombok.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductDto {

    private Long id;
    private String name;
    private String description;
    private Double price;
    private Integer stock;
}
07

@RequiredArgsConstructor ក្នុង Service

ជំនួស @Autowired ដោយប្រើ Constructor Injection ជាមួយ @RequiredArgsConstructor — វិធីដែល Spring ណែនាំ:

❌ @Autowired (មិនល្អ)
@Service
public class ProductService {

  @Autowired
  private ProductRepository repo;

  @Autowired
  private ProductMapper mapper;
}
✅ @RequiredArgsConstructor
@Service
@RequiredArgsConstructor
public class ProductService {

  private final ProductRepository repo;
  private final ProductMapper mapper;

  // Lombok inject constructor!
}
ProductService.java — Full Example
package com.example.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductService {

    private final ProductRepository productRepository;

    public List<Product> getAllProducts() {
        log.info("Fetching all products...");
        return productRepository.findAll();
    }

    public Product createProduct(ProductDto dto) {
        log.info("Creating product: {}", dto.getName());

        Product product = Product.builder()
                .name(dto.getName())
                .description(dto.getDescription())
                .price(dto.getPrice())
                .stock(dto.getStock())
                .build();

        return productRepository.save(product);
    }
}
08

@Builder Pattern

@Builder ជួយ construct object ក្នុង readable style ពិសេសសម្រាប់ object ដែលមាន fields ច្រើន:

ការប្រើ @Builder
// ❌ Constructor ធម្មតា — ច្រឡំ arguments
Product p = new Product(null, "Phone", "Smartphone", 299.99, 50);

// ✅ Builder Pattern — ច្បាស់លាស់
Product product = Product.builder()
        .name("iPhone 16")
        .description("Apple Smartphone")
        .price(999.99)
        .stock(100)
        .build();

// @Builder ជាមួយ default value
@Builder.Default
private Boolean active = true;

@Builder.Default
private LocalDateTime createdAt = LocalDateTime.now();
09

@Slf4j — Logging

ជំនួស Logger logger = LoggerFactory.getLogger(...) ដ៏វែងដោយ @Slf4j:

❌ មុន Lombok
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyController {
  private static final
    Logger log =
    LoggerFactory
    .getLogger(
      MyController.class
    );
}
✅ ប្រើ @Slf4j
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MyController {

  // ប្រើ log បានភ្លាម!
  log.info("Hello {}", name);
  log.error("Error: {}", e);
  log.debug("Debug msg");
}
10

ឧទាហរណ៍: REST Controller

ProductController.java
package com.example.demo.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/api/products")
@RequiredArgsConstructor
public class ProductController {

    private final ProductService productService;

    @GetMapping
    public ResponseEntity<?> getAll() {
        log.info("GET /api/products");
        return ResponseEntity.ok(
            productService.getAllProducts()
        );
    }

    @PostMapping
    public ResponseEntity<?> create(
            @RequestBody ProductDto dto) {
        log.info("POST /api/products: {}", dto);
        return ResponseEntity.ok(
            productService.createProduct(dto)
        );
    }
}
11

Tips & Best Practices

ប្រើ @RequiredArgsConstructor ជាមួយ final fields ជំនួស @Autowired — Spring ណែនាំ constructor injection
ℹ️ @Data ក្នុង Entity — ខ្លះណែនាំប្រើ @Getter @Setter @ToString(exclude="...") ដើម្បីជៀស lazy loading infinite loop
⚠️ @Builder + @NoArgsConstructor — ពេលប្រើ @Builder ជាមួយ @NoArgsConstructor ត្រូវបន្ថែម @AllArgsConstructor ផងដែរ
💡 @Value — ប្រើសម្រាប់ immutable class (ដូចជា @Data ប៉ុន្តែ fields ជា final ទាំងអស់)
ឧទាហរណ៍ @Value — Immutable DTO
import lombok.Value;

@Value // fields ទាំងអស់ final + @Getter only
public class ErrorResponse {
    String message;
    Integer statusCode;
    String timestamp;
}

// ប្រើ:
var err = new ErrorResponse(
    "Not Found", 404, "2025-01-01"
);

SUMMARY
Annotations ដែលប្រើញឹកញាប់ក្នុង Spring Boot
@Data @Getter / @Setter @Builder @NoArgsConstructor @AllArgsConstructor @RequiredArgsConstructor @Slf4j @Value @ToString