簡體   English   中英

不要使用 Spring JPA 更新實體中未指定的字段

[英]Do not update not specified fields in Entity with Spring JPA

我正在使用 REST API 創建一個應用程序,因此端點之一是創建,另一個端點是更新。 當我嘗試更新實體時,我的問題就出現了,它更新了我在創建中添加但不在更新中添加的字段。 我正在嘗試使用@DynamicUpdate@SelectBeforeUpdate ,但它仍然遵循相同的行為。

控制器

@RestController
@RequestMapping("/v01")
@Slf4j
public class ProjectController {

@Autowired
private ProjectServiceIface projectService;


@PostMapping(path = "/project", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Project> createProject(@Valid @RequestBody Project project, BindingResult result){
    if(result.hasErrors()){
        throw new BusinessServiceException(result.getFieldError().getDefaultMessage(), result.getFieldError().getField() + " " + result.getFieldError().getCode());
    }
    Project projectSaved = projectService.createProject(project);
    HttpHeaders headers = new HttpHeaders();
    headers.add("Location", projectSaved.getId().toString());

    return new ResponseEntity<>(project, headers, HttpStatus.CREATED);
}

@PatchMapping(path = "/project", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Project> updateProject(@Valid @RequestBody Project project, BindingResult result){
    if(result.hasErrors()){
        throw new BusinessServiceException(result.getFieldError().getDefaultMessage(), result.getFieldError().getField() + " " + result.getFieldError().getCode());
    }
    Project projectUpdated = projectService.updateProject(project);

    if(projectUpdated == null) {
        return new ResponseEntity<>(null, new HttpHeaders(), HttpStatus.NOT_FOUND);
    }
    HttpHeaders headers = new HttpHeaders();
    headers.add("Location", projectUpdated.getId().toString());

    return new ResponseEntity<>(projectUpdated, headers, HttpStatus.CREATED);
}
}

服務

@Service
public class ProjectServiceImpl implements ProjectServiceIface {

@Autowired
private ProjectRepository projectRepository;

@Autowired
private ProjectRepository projectRepository;

@Override
public Project createProject(Project project) {
    Project projectFound = projectRepository.findByName(project.getName());
    if(projectFound != null){
        throw new BusinessServiceException(Constants.FUNCTIONAL_ERROR, "The Project already exists");
    }
    project.setCreateTime(new Date());

    Project projectSaved = projectRepository.save(project);
    return projectSaved;
}

@Override
public Project findProjectById(String id) {
    Project projectFound = null;
    if(!StringUtils.isNumeric(id)){
        throw new BusinessServiceException(Constants.FUNCTIONAL_ERROR, "The ID is not in a correct format");
    }
    Optional<Project> projectOptional = projectRepository.findById(Integer.valueOf(id));
    if(projectOptional.isPresent()){
        projectFound = projectOptional.get();
    }
    return projectFound;
}

@Override
public Project updateProject(Project project) {
    Project projectUpdated = null;
    Optional<Project> projectFound = projectRepository.findById(project.getId());
    if(projectFound.isPresent()){
        project.setUpdateTime(new Date());
        //Project projectMapped = EntityMapper.projectMapper(project);
        projectUpdated = projectRepository.save(project);
    }
    return projectUpdated;
}

@Override
public Project findProjectByName(String projectName) {
    Project project = projectRepository.findByName(projectName);

    return project;
}
}

存儲庫

public interface ProjectRepository extends CrudRepository<Project, Integer> {

@Query(value = "SELECT * FROM project p WHERE p.name = :projectName", nativeQuery = true)
Project findByName(String projectName);

 }

項目(實體)

@Entity
@Data
@DynamicUpdate
@SelectBeforeUpdate
@Table(name = "project")
public class Project implements Serializable {
private static final long serialVersionUID = -6163778458602900643L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@NotEmpty
private String name;
@NotEmpty
private String tag;
private String icon;
@Column(name = "create_user", updatable = false)
private String createUser;
@Column(name = "update_user")
private String updateUser;
@Column(name = "create_time", updatable = false)
private Date createTime;
@Column(name = "update_time")
private Date updateTime;
}

這是我用於創建的請求:

{
"name" : "Test12",
"tag" : "TST",
"icon" : "/var/usr"
}

我得到的回應:

{
"id": 5,
"name": "Test12",
"tag": "TST",
"icon": "/var/usr",
"createUser": null,
"updateUser": null,
"createTime": "2020-01-24T22:33:48.499+0000",
"updateTime": null
}

這是我執行更新的請求:

{
"id": 5,
"name": "Test5",
"tag": "AAA"
}

我得到的回應:

{
"id": 5,
"name": "Test67",
"tag": "AAA",
"icon": null,
"createUser": null,
"updateUser": null,
"createTime": null,
"updateTime": "2020-01-24T22:44:50.914+0000"
}

如您所見, iconcreateTime都已設置為 null。 我只想更新我在請求/實體中發送的字段。

您可以使用 Spring Data Rests Patch 方法,或在 EntityManager 上顯式調用合並

如果您共享您在創建時嘗試插入/更新的代碼,則在實體類中刪除可更新 = false 會很有幫助

問題是您沒有從數據庫中獲取 Project 的值 ..如果該值存在,您正在檢查 DB,但在 Project Json 圖標中保存以 json 發送的值不存在

修復是您需要根據 ID 獲取值並再次設置將要更改的值..這樣將檢索舊值並更新新值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM