@Notnull при обновлении, а не при добавлении

У меня есть класс модели, который используется в post (create) и put (update) rest API.

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@Entity(name= "employee")
public class employeeDetail {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long employeeId;
    @NonNull
    private String employeeName;

}

Таким образом, поскольку идентификатор сотрудника должен быть обнуляемым при добавлении, его необходимо передать при операции обновления. Что лучше реализовать?

Примечание. В этом случае идентификатор сотрудника является первичным ключом, такая же ситуация возможна и для полей непервичного ключа. Я использую Spring boot, Spring data JPA и hibernate. База данных mariadb.

Можете ли вы сделать employeeId Integer не int? int имеет значение по умолчанию = 0, Integer по умолчанию = null. Это может решить вашу проблему. PS. Лучше сделать Long...

Andrii Vdovychenko 01.02.2019 13:25

О первичном ключе Long, пожалуйста, проверьте здесь

Andrii Vdovychenko 01.02.2019 13:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
2
228
2

Ответы 2

Поскольку вы ожидаете, что Hibernate сгенерирует ваш идентификатор при вставке, он должен быть обнуляемым, поэтому его тип.

Просто измените employeeId на Integer.


С точки зрения дизайна рассмотрите возможность создания 2 разных классов домена бизнеса: один для вставки без идентификатора и один для обновления/выбора с идентификатором, не допускающим значение NULL.

public class EmployeeRegistration {
    @NonNull
    private String name;
}

public class EmployeeDetail {
    @NonNull
    private Integer employeeId;
    @NonNull
    private String name;
}

Затем предоставьте методы для преобразования их в объекты базы данных.

Что-то вроде этого:

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.transaction.Transactional;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Optional;


@Getter
@Setter
@NoArgsConstructor
@Entity(name = "employee")
class EmployeeDetail {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long employeeId; //Long is better!

    @NotNull
    private String employeeName;


    //    Needed just for conversion -> use some mapper, and remove this constructor
    public EmployeeDetail(EmployeeDetailDTO employeeDetailDTO) {
        this.employeeId = employeeDetailDTO.getEmployeeId();
        this.employeeName = employeeDetailDTO.getEmployeeName();
    }
}

interface EmployeeDetailRepo extends JpaRepository<EmployeeDetail, Long> {
}

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
class EmployeeDetailDTO {

    private Long employeeId;

    @NotNull
    private String employeeName;

//    Other fields

    //    Needed just for conversion -> use some mapper, and remove this constructor
    public EmployeeDetailDTO(EmployeeDetail employeeDetail) {
        this.employeeId = employeeDetail.getEmployeeId();
        this.employeeName = employeeDetail.getEmployeeName();
    }
}

@Service
class EmpDetailService {

    private EmployeeDetailRepo employeeDetailRepo;

    @Autowired
    public EmpDetailService(EmployeeDetailRepo employeeDetailRepo) {
        this.employeeDetailRepo = employeeDetailRepo;
    }

    public EmployeeDetailDTO add(EmployeeDetailDTO employeeDetailDTO) {
//        map EmployeeDetailDTO to EmployeeDetail
        EmployeeDetail employeeDetail = new EmployeeDetail(employeeDetailDTO);
        EmployeeDetail employeeDetail1FromDB = employeeDetailRepo.save(employeeDetail);
//        map back to dto
        return new EmployeeDetailDTO(employeeDetail1FromDB);
    }

    @Transactional
    public EmployeeDetailDTO edit(Long id, EmployeeDetailDTO employeeDetailDTO) {
//        map EmployeeDetailDTO to EmployeeDetail
        Optional<EmployeeDetail> byId = employeeDetailRepo.findById(id);
        EmployeeDetail employeeDetailFromDB = byId.orElseThrow(() -> new RuntimeException("No such user with id: " + id));
        employeeDetailFromDB.setEmployeeName(employeeDetailDTO.getEmployeeName());
        return new EmployeeDetailDTO(employeeDetailFromDB);
    }
}

@RequestMapping
class Controller {
    private EmpDetailService empDetailService;

    @Autowired
    Controller(EmpDetailService empDetailService) {
        this.empDetailService = empDetailService;
    }

    @PostMapping("/add")
    public ResponseEntity<EmployeeDetailDTO> add(@Valid @RequestBody EmployeeDetailDTO employeeDetailDTO) {
        EmployeeDetailDTO added = empDetailService.add(employeeDetailDTO);
        return new ResponseEntity<>(added, HttpStatus.OK);
    }

    @PostMapping("/edit/{id}")
    public ResponseEntity<EmployeeDetailDTO> edit(@PathVariable Long id,
                                                  @Valid @RequestBody EmployeeDetailDTO employeeDetailDTO) {
        EmployeeDetailDTO edited= empDetailService.edit(id, employeeDetailDTO);
        return new ResponseEntity<>(edited, HttpStatus.OK);
    }
}

Другие вопросы по теме