简体   繁体   English

Spring 启动 JPA 更新仅更新特定字段

[英]Spring boot JPA update to update only specific fields

So I encountered this issue with updating an entity in DB.所以我在更新数据库中的实体时遇到了这个问题。 while Passing a whole entity and updating only specific fields it treats untouched fields as null, as a result I get an exception since those fields are @Not-Null ,在传递整个实体并仅更新特定字段时,它将未触及的字段视为 null,因此我得到一个异常,因为这些字段是@Not-Null

I have tried looking for similar problems but could not fix my problem.我曾尝试寻找类似的问题,但无法解决我的问题。

Company ENTITY:公司实体:

@Entity
@Table (name = "companies")
@Data
@ToString(exclude = "perfumes")
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Company {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @NotNull
    private String name;

    @NotNull
    @Email(message = "Wrong input. please enter a VALID email address")
    private String email;

    @NotNull
    @Size(min = 4, max = 14, message = "Password range must be between 4 - 14 digits")
    private String password;

    @NotNull
    @Enumerated(EnumType.STRING)
    private Country country;

    @Singular
    @OneToMany(mappedBy = "company", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Perfume> perfumes = new ArrayList<>();
}

Most fields are @NotNull for creation, however, I need to update the entity, sometimes only specific fields.大多数字段都是@NotNull用于创建,但是,我需要更新实体,有时只更新特定字段。

Service:服务:

@Override
public String updateCompany(int id, Company company) throws DoesNotExistException {
    if(!companyRepository.existsById(id))
    {
        throw new DoesNotExistException(id);
    }

    companyRepository.saveAndFlush(company);
    return company.getName() + " has been UPDATED";
}

as you can see an ENTITY has been passed which causes rest of attributes to be automatically null if not modified.如您所见,已传递一个ENTITY ,如果未修改,则会导致属性的 rest 自动为 null。

Controller: Controller:

  @PutMapping("/updateCompany/{id}")
    @ResponseStatus(HttpStatus.ACCEPTED)
    public String updateCompany(@PathVariable int id, @RequestBody Company company) throws DoesNotExistException {
        return admin.updateCompany(id,company);
    }

EXCEPTION:例外:

Validation failed for classes [com.golden.scent.beans.Company] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='must not be null', propertyPath=password, rootBeanClass=class com.golden.scent.beans.Company, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]

Thanks.谢谢。

The controller is binding the values you pass in to a new Company entity. controller 将您传入的值绑定到新的公司实体。 The new entity is not attached to the persistence context, it does not have the state of the pre-existing entity.新实体未附加到持久性上下文,它没有预先存在的实体的 state。 When you save it JPA thinks you want to null out all the fields you don't have values for.当您保存它时 JPA 认为您想要 null 出所有您没有值的字段。

Instead, you could have the controller bind its arguments to a DTO.相反,您可以让 controller 将其 arguments 绑定到 DTO。 Then in the service you look up the existing Customer, using findById, and copy the fields you want updated from the DTO to the entity.然后在服务中使用 findById 查找现有客户,并将要更新的字段从 DTO 复制到实体。 Then call saveAndFlush passing in the updated entity.然后调用 saveAndFlush 传入更新的实体。

It looks like there's an improvement over the DTO, you can use aJsonPatch to hold the updates passed in, see https://www.baeldung.com/spring-rest-json-patch On the server the important thing is to look up the existing entity so that you have an entity that is attached to the persistence context and has all its fields current.看起来比 DTO 有所改进,你可以使用 aJsonPatch 来保存传入的更新,请参阅https://www.baeldung.com/spring-rest-json-patch在服务器上重要的是查找现有实体,以便您拥有一个附加到持久性上下文并使其所有字段都处于当前状态的实体。

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

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