Skip to content
Spring Boot sb lombok 3 min read

@Builder

@Builder implements the builder pattern for you, giving callers a fluent, readable way to construct objects with many fields. It is especially valuable for DTOs and value objects that have several optional fields, where a long positional constructor would be hard to read and easy to get wrong.

Fluent construction

Annotate a class (or a constructor/static method) with @Builder and Lombok generates a static builder() method plus a chainable setter for each field.

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class UserDto {
    private Long id;
    private String name;
    private String email;
    private boolean active;
}

Callers construct instances fluently, naming each value explicitly:

UserDto user = UserDto.builder()
        .id(1L)
        .name("Ada Lovelace")
        .email("[email protected]")
        .active(true)
        .build();

Compare this with a positional constructor call like new UserDto(1L, "Ada Lovelace", "[email protected]", true) — the builder is self-documenting and order-independent.

@Builder.Default for default values

A field initializer is ignored by the builder unless you mark it @Builder.Default. Without the annotation, an unset field falls back to the Java default (null, 0, false), not your initializer.

@Getter
@Builder
public class SearchRequest {
    private String query;

    @Builder.Default
    private int page = 0;

    @Builder.Default
    private int size = 20;
}
SearchRequest req = SearchRequest.builder().query("lombok").build();
// req.getPage() == 0, req.getSize() == 20  (defaults applied)

Warning: Forgetting @Builder.Default is a common bug. A field written as private int size = 20; will be 0 when built unless the annotation is present.

@Singular for collections

@Singular lets callers add collection elements one at a time and produces an immutable collection in the built object. Lombok also derives a sensible singular method name.

import lombok.Builder;
import lombok.Getter;
import lombok.Singular;

@Getter
@Builder
public class Order {
    private Long id;

    @Singular
    private List<String> items;     // add via .item(...)

    @Singular("tag")
    private Set<String> tags;        // custom singular name
}
Order order = Order.builder()
        .id(100L)
        .item("Keyboard")
        .item("Mouse")
        .tag("electronics")
        .tag("priority")
        .build();
// order.getItems() == [Keyboard, Mouse] (immutable)

The builder also exposes plural methods (.items(collection)) and a .clearItems() method.

toBuilder for copy-and-modify

Set toBuilder = true to add an instance method that pre-fills a new builder with the current object’s values — ideal for creating a modified copy of an immutable object.

@Getter
@Builder(toBuilder = true)
public class Config {
    private String host;
    private int port;
    private boolean tls;
}
Config base = Config.builder().host("localhost").port(8080).tls(false).build();
Config secure = base.toBuilder().tls(true).build(); // copies host/port, flips tls

Builders for DTOs in Spring Boot

@Builder pairs naturally with immutable response DTOs. Combine it with @Getter (not @Setter) so the object is read-only after construction, and let a service map an entity into the DTO:

@Service
@RequiredArgsConstructor
public class UserMapper {

    public UserDto toDto(User entity) {
        return UserDto.builder()
                .id(entity.getId())
                .name(entity.getName())
                .email(entity.getEmail())
                .active(entity.isActive())
                .build();
    }
}

This keeps construction explicit and the DTO immutable, which is the recommended shape for API responses.

Tip: Place @Builder on a constructor or static factory method (rather than the class) when you want the builder to cover only a subset of fields, or to coexist with an @AllArgsConstructor. For deserialization of incoming JSON into a builder-based type, add Jackson’s @JsonDeserialize(builder = ...) or annotate with @Jacksonized.

Last updated June 13, 2026
Was this helpful?