简体   繁体   English

不要使用 Spring JPA 更新实体中未指定的字段

[英]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.我正在使用 REST API 创建一个应用程序,因此端点之一是创建,另一个端点是更新。 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.我正在尝试使用@DynamicUpdate@SelectBeforeUpdate ,但它仍然遵循相同的行为。

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.如您所见, iconcreateTime都已设置为 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如果您共享您在创建时尝试插入/更新的代码,则在实体类中删除可更新 = false 会很有帮助

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问题是您没有从数据库中获取 Project 的值 ..如果该值存在,您正在检查 DB,但在 Project Json 图标中保存以 json 发送的值不存在

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修复是您需要根据 ID 获取值并再次设置将要更改的值..这样将检索旧值并更新新值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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