如何在不使用 Java Spring Boot 插入新值的情况下更新 table 中的现有值

How to update existing value in table without inserting new using Java SpringBoot

我有两个 table,一个是 parent,另一个是 child。当我最初尝试保存时,如果 Parent table 中不存在值,我可以在两个 table 中插入值。但是在 update/insert child table 中的值时,它正在插入重复值。

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RuleApi {
    Long id;
    private String market;
    private int modelYear;
    private String vehicleLine;
    private String vehicleLineName;
    private String locale;
    private String binding;
    private String description;
    private String createUser;
    private String updateUser;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DescriptorSaveRequest {
    @Valid
    @NotNull
    RuleApi rule;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "MNAVS03_DESCRIPTOR_CONTEXT")
@EntityListeners(AuditingEntityListener.class)
public class DescriptorContext implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Setter(value = AccessLevel.NONE)
    @Column(name = "NAVS03_DESCRIPTOR_CONTEXT_K")
    private Long id;

    @Column(name = "NAVS03_MARKET_N")
    private String market;

    @Column(name = "NAVS03_MODEL_YEAR_R")
    private Integer modelYear;

    @Column(name = "NAVS03_VEHICLE_LINE_C")
    private String vehicleLine;

    @Column(name = "NAVS03_VEHICLE_LINE_N")
    private String vehicleLineName;

    @Column(name = "NAVS03_LOCALE_N")
    private String locale;

    @Column(name = "NAVS03_CREATE_USER_C", nullable = false)
    private String createUserId;

    @CreationTimestamp
    @Column(name = "NAVS03_CREATE_S")
    private Timestamp createTimestamp;

    @Column(name = "NAVS03_LAST_UPDT_USER_C", nullable = false)
    private String updateUserId;

    @UpdateTimestamp
    @Column(name = "NAVS03_LAST_UPDT_S")
    private Timestamp updateTimestamp;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "MNAVS04_DESCRIPTOR_RULE")
@EntityListeners(AuditingEntityListener.class)
public class DescriptorRule implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Setter(value = AccessLevel.NONE)
    @Column(name = "NAVS04_DESCRIPTOR_RULE_K")
    private Long id;

    @JoinColumn(name = "NAVS03_DESCRIPTOR_CONTEXT_K", nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
    private DescriptorContext descriptorContextId;

    @Column(name = "NAVS04_BINDING_N",
    unique = true)
    private String binding;

    @Column(name = "NAVS04_DESCRIPTOR_RULE_X")
    private String description;

    @Column(name = "NAVS04_CREATE_USER_C", nullable = false)
    private String createUserId;

    @CreationTimestamp
    @Column(name = "NAVS04_CREATE_S")
    private Timestamp createTimestamp;

    @Column(name = "NAVS04_LAST_UPDT_USER_C", nullable = false)
    private String updateUserId;

    @UpdateTimestamp
    @Column(name = "NAVS04_LAST_UPDT_S")
    private Timestamp updateTimestamp;
}

@ApiOperation(value = "Create/Update Feature Descriptions", notes = "Create/Update a descriptions based on the given input")
@PostMapping("/descriptor/saveFeatures")
public ResponseEntity<BaseBodyResponse<String>> saveFeatureDescriptions(@Valid @RequestBody DescriptorSaveRequest descriptorSaveRequest) throws Exception {
        this.descriptorContextService.saveFeatureDescriptions(
                this.descriptorContextMapper.mapDescriptorContext(descriptorSaveRequest),
                this.descriptorContextMapper.mapDescriptorRule(descriptorSaveRequest)
        );
        return ResponseEntity.ok(BaseBodyResponse.result("Saved Successfully"));
}

@Service
public class DescriptorContextService {
//SaveFeatureDescriptions
    public void saveFeatureDescriptions(DescriptorContext descriptorContext, DescriptorRule descriptorRule) throws Exception {
        DescriptorContext descriptorContext1 =
                this.descriptorContextRepository.findByMarketAndModelYearAndVehicleLineAndVehicleLineNameAndLocale(
                        descriptorContext.getMarket(),
                        descriptorContext.getModelYear(),
                        descriptorContext.getVehicleLine(),
                        descriptorContext.getVehicleLineName(),
                        descriptorContext.getLocale());
        if (descriptorContext1 == null) {
            // add a new context
            descriptorContext1 = descriptorContextRepository.save(DescriptorContext.builder()
                    .market(descriptorContext.getMarket())
                    .modelYear(descriptorContext.getModelYear())
                    .vehicleLine(descriptorContext.getVehicleLine())
                    .vehicleLineName(descriptorContext.getVehicleLineName())
                    .locale(descriptorContext.getLocale())
                    .createUserId(descriptorContext.getCreateUserId())
                    .updateUserId(descriptorContext.getUpdateUserId())
                    .build());
        }

        Long contextId = descriptorContext1.getId();
        List<DescriptorRule> rule = this.descriptorRuleRepository.findByDescriptorContextId(contextId);
        if (rule.size() == 0) {
            // add a new rule
            this.descriptorRuleRepository.save(DescriptorRule.builder()
                    .descriptorContextId(descriptorContext1)
                    .binding(descriptorRule.getBinding())
                    .description(descriptorRule.getDescription())
                    .createUserId(descriptorContext.getCreateUserId())
                    .updateUserId(descriptorContext.getUpdateUserId())
                    .build());

        } else {
            // update a existing rule
            for (DescriptorRule descriptorRule1 : rule) {
                if (descriptorRule1.getBinding().equals(descriptorRule.getBinding())) {
                    descriptorRule1.setDescription(descriptorRule.getDescription());
                    descriptorRule1.setupdateUserId(descriptorRule.getupdateUserId());
                    this.descriptorRuleRepository.save(descriptorRule1);
                }  else {
                        this.descriptorRuleRepository.save(DescriptorRule.builder()
                                .descriptorContextId(descriptorContext1)
                                .binding(descriptorRule.getBinding())
                                .description(descriptorRule.getDescription())
                                .createUserId(descriptorContext.getCreateUserId())
                                .updateUserId(descriptorContext.getUpdateUserId())
                                .build());
                    }
                }
            }
        }
    }
}



@Component
public class DescriptorContextMapper {
        public DescriptorContext mapDescriptorContext(DescriptorSaveRequest descriptorSaveRequest) {
        return DescriptorContext.builder()
                .market(descriptorSaveRequest.getRule().getMarket())
                .vehicleLine(descriptorSaveRequest.getRule().getVehicleLine())
                .vehicleLineName(descriptorSaveRequest.getRule().getVehicleLineName())
                .modelYear(descriptorSaveRequest.getRule().getModelYear())
                .locale(descriptorSaveRequest.getRule().getLocale())
                .createUserId(descriptorSaveRequest.getRule().getCreateUser())
                .updateUserId(descriptorSaveRequest.getRule().getUpdateUser())
                .build();
    }

    public DescriptorRule mapDescriptorRule(DescriptorSaveRequest descriptorSaveRequest) {
        return DescriptorRule.builder()
                .id(descriptorSaveRequest.getRule().getId())
                .binding(descriptorSaveRequest.getRule().getBinding())
                .description(descriptorSaveRequest.getRule().getDescription())
                .createUserId(descriptorSaveRequest.getRule().getCreateUser())
                .updateUserId(descriptorSaveRequest.getRule().getUpdateUser())
                .build();
    }
}

{
  "rule": {
    "binding": "5003",
    "description": "Test new 5003-2023 Escape",
    "locale": "fr_CA",
    "market": "WANAC",
    "modelYear": 2023,
    "vehicleLine": "TMC",
    "vehicleLineName": "Escape",
    "createUser": "rdongre",
    "updateUser": "rdongre"
  }
}

如果我正在传递此请求并且值不存在于两个 table 中,那么它应该将值插入两个 table 中,这与上面的代码按预期工作。但是在更新时它进入循环并插入重复值。我正在尝试更新 child table 中的 DESCRIPTION 如果存在 BINDING 如果不存在则应该插入 BINDING 加上 DESCRIPTION

我通过分离保存和更新方法解决了这个问题。感谢大家。