简体   繁体   中英

Do not update not specified fields in Entity with Spring JPA

I am creating an application with REST API so one of the endpoints is to create and another to update. My issue comes when I try to update the entity it updates the fields I added in the creation but not in the update. I am trying with @DynamicUpdate and @SelectBeforeUpdate and it still follows the same behaviour.

Controller

@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

@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;
}
}

Repository

public interface ProjectRepository extends CrudRepository<Project, Integer> {

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

 }

Project (Entity)

@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;
}

This is the request I use for creating:

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

The response I obtain:

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

And this is the request I perform to update:

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

The response I obtain:

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

As you can see both icon and createTime have been set to null. I only want to be updated specifically the fields I send in the request/entity.

您可以使用 Spring Data Rests Patch 方法,或在 EntityManager 上显式调用合并

it would be helpful if you share the code that you are trying to insert/update for creation time remove updatable = false in entity class

Issue is you are not getting the values for Project from database ..you are checking in DB if the value exists but saving the values sent in json in Project Json icon is not there

fix is you need to get the values based on ID and set the values again which are going to be changed..this way old values willl be retrieved and new values will be updated

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM