@ Не при обновлении, а при добавлении - PullRequest
0 голосов
/ 01 февраля 2019

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

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.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Примерно так:

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);
    }
}
0 голосов
/ 01 февраля 2019

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

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


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

public class EmployeeRegistration {
    @NonNull
    private String name;
}

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

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

...