Prevent Unintended Field Updates in SpringBoot: DTOs vs @InitBinder

This article explains how SpringBoot's default data binding can unintentionally modify unwanted fields and demonstrates three safe approaches—using a dedicated DTO, configuring WebDataBinder with @InitBinder to allow only specific fields, and applying advanced @InitBinder options such as required fields, constructor‑only binding, and custom validators—to ensure precise and secure request parameter handling.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Prevent Unintended Field Updates in SpringBoot: DTOs vs @InitBinder

1. Introduction

In SpringBoot, request parameters are bound to model objects by default, which can unintentionally update fields that should not be modified. The article demonstrates this risk with a User entity containing age, name, password, and email.

public class User {
    private Integer age;
    private String name;
    private String password;
    private String email;
    // getters and setters
}

A controller method receives a User instance and updates it via MyBatis:

@GetMapping("/updateBasicInfo")
public R updateAgeAndEmail(User user) {
    // update operation
    userMapper.updateUserInfo(user);
    return R.success("更新成功");
}

Without restricting binding, a client could supply values for name or password, leading to unintended changes.

2. Solutions

2.1 Use a DTO

Create a DTO that contains only the fields that should be updatable, then copy its values to the User entity in the service layer.

public class UserBasicDTO {
    private Integer age;
    private String email;
    // getters and setters
}

Change the controller to accept the DTO:

@GetMapping("/updateBasicInfo")
public R updateAgeAndEmail(UserBasicDTO dto) {
    // copy dto to User and update
}

2.2 Use @InitBinder

Configure a WebDataBinder to allow only specific fields:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setAllowedFields("age", "email");
}

Alternatively, disallow fields: binder.setDisallowedFields("name", "password"); For constructor‑only binding, enable declarative binding:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDeclarativeBinding(true);
}

Define a constructor in the entity that accepts only the allowed parameters:

public static class User {
    private Integer age;
    private String email;
    public User(Integer age, String email) {
        this.age = age;
        this.email = email;
    }
}

If multiple constructors exist, Spring will raise an error (illustrated in the following image):

Multiple constructors error
Multiple constructors error

Additional @InitBinder configurations:

Require certain fields:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setRequiredFields("id");
}

If the required field is missing, Spring throws an exception (shown below):

Missing required field error
Missing required field error

Custom validators can also be added:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.addValidators(new UserValidator());
}
public class UserValidator implements Validator {
    public boolean supports(Class<?> clazz) {
        return User.class.isAssignableFrom(clazz);
    }
    public void validate(Object target, Errors errors) {
        User user = (User) target;
        if (user.getAge() < 0) {
            errors.reject("user.error.age", "年龄错误");
        }
    }
}

When validation fails, Spring returns a binding exception (illustrated in the image):

Validation error
Validation error
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

dtoSpringBootdata bindingInitBinderWebDataBinder
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.