Plus Ultra
Plus Ultra

Reputation: 139

Update User Detail api returns DataIntegrityViolationException

I'm creating an update API that updates the profile of the super admin, I mapped the member table to a DTO, on the member table password is set to not null and I did not include the password field on the dto because there's a provision for that be, when I tested the API on postman it returned on the console

DataIntegrityViolationException
SQL Error: 1048, SQLState: 23000
Column 'password' cannot be null

Here is my code

Dto

@Getter
@Setter
public class UpdateProfileDto {

    @NotNull(message = "{member.firstName.notNull}")
    @JsonProperty("first_name")
    private String firstName;

    @NotNull(message = "{member.lastName.notNull}")
    @JsonProperty("last_name")
    private String lastName;

    @JsonProperty("nationality")
    private Long nationality;

    @JsonProperty("country_of_residence")
    private Long countryOfResidence;

    @JsonProperty("date_of_birth")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    @JsonFormat(pattern = "dd-MM-yyyy")
    @Past(message = "{customer.dateOfBirth.past}")
    private Date dateOfBirth;

    @JsonProperty("current_job_title")
    private String currentJobTitle;

    @NotNull(message = "{member.emailAddress.notNull}")
    @JsonProperty("email_address")
    private String emailAddress;

    @JsonProperty("username")
    private String username;

    @NotNull(message = "{member.phoneNumber.notNull}")
    @PhoneNumber
    @JsonProperty("phone_number")
    private String phoneNumber;

    @Size(max = 300, message = "{member.city.size}")
    @JsonProperty("city")
    private String city;

    @Size(max = 300, message = "{member.state.size}")
    @JsonProperty("state")
    private String state;
}

ServiceImpl

@Override
    @Transactional
    public Member updateProfile(UpdateProfileDto body) {
        Member superAdmin = repository.getOne(id);
        if (superAdmin == null) {
            throw new MemberNotFoundException(id);
        }

        Optional<Role> existingRole = roleJpaRepository.findByCode(RoleType.SUPER_ADMINISTRATOR.getValue());
        if (existingRole.isEmpty()) {
            throw new RoleNotFoundException(RoleType.SUPER_ADMINISTRATOR.getValue());
        }

        Member existing;

        existing = mapper.map(body, Member.class);
        existing.setPassword(superAdmin.getPassword());
        existing.getRoles().add(existingRole.get());
        existing.setNationality(countryRepository.getOne(body.getNationality()));
        existing.setCountryOfResidence(countryRepository.getOne(body.getCountryOfResidence()));
        return adminJpaRepository.save(existing);
    }

Controller

@RestController
@RequestMapping(
        value = "super-admin",
        produces = { MediaType.APPLICATION_JSON_VALUE }
)
public class SuperAdminController {
    private final SuperAdminService service;
    public SuperAdminController(SuperAdminService service) {
        this.service = service;
    }

    @PutMapping("/update")
    public Member updateProfile(@Valid @RequestBody UpdateProfileDto body){
        Member superAdmin =  service.updateProfile(body);
        return superAdmin;
    }
}

The password bug has been fixed(changes reflected in serviceImpl), but when I run the code it returned Duplicate entry '[email protected]' for key 'member.email_address_phone_number_uq' email, and the phone number is set as a unique constraint in the member table, how can I bypass this?

Upvotes: 0

Views: 38

Answers (1)

Chaosfire
Chaosfire

Reputation: 6995

You have few options, depending on your exact use case.

  1. Extract existing password, using unique property in UpdateProfileDto, email looks like it can do the job.

Pseudocode:

Member existing = repository.findByEmail;
Member superAdmin = mapper.map(body, Member.class);
superAdmin.setPassword(existing.getPassword());
  1. Set a dummy value for password, to be updated later on.
superAdmin.setPassword("dummy-password");
  1. Make the column nullable in database.

Upvotes: 1

Related Questions