【问题标题】:I want update entity but dataintegrityviolationexception: could not execute statement SQL [n/a]; constraint SGB.C_PR_PK] occurs我想要更新实体但 dataintegrityviolationexception: could not execute statement SQL [n/a];约束 SGB.C_PR_PK] 发生
【发布时间】:2022-01-07 12:59:53
【问题描述】:

实体

@Entity
@Table(name = "v_CUSTOMER", uniqueConstraints = {@UniqueConstraint(columnNames = {"accno", "row"})})
@SequenceGenerator(
        name = "sgb.CUSTOMER_SEQ",
        sequenceName = "sgb.CUSTOMER_SEQ",
        allocationSize = 1
)
@Getter
@Setter
@ToString
@FieldNameConstants
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sgb.CUSTOMER_SEQ")
    @Column(name = "NEWLAB_CHRONO", nullable = true, insertable = true, updatable = true, precision = 0)
    @CobolType(numeric = true,nullable = true)
    private Integer newlabChrono;

    @Basic
    @Column(name = "ACCNO", nullable = false, insertable = true, updatable = true, length = 10)
    @CobolType(numeric = true)
    private String accno;

    @Basic
    @Column(name = "ROW", nullable = false, insertable = true, updatable = true, length = 2)
    @CobolType(numeric = true)
    private String row;

    @Basic
    @Column(name = "SHAKHS", nullable = true, insertable = true, updatable = true, length = 1)
    @CobolType(numeric = true)
    private String shakhs;

    @Basic
    @Column(name = "TAR_GAR", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true)
    private String tarGar;

    @Basic
    @Column(name = "ID_ALT1", nullable = true, insertable = true, updatable = true, length = 12)
    @CobolType(numeric = true)
    private String idAlt1;

    @Basic
    @Column(name = "ID_ALT2", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true)
    private String idAlt2;

    @Basic
    @Column(name = "ID_ALT3", nullable = true, insertable = true, updatable = true, length = 3)
    @CobolType(numeric = true)
    private String idAlt3;

    @Basic
    @Column(name = "MELLI_ALT", nullable = true, insertable = true, updatable = true, length = 12)
    @CobolType(numeric = true)
    private String melliAlt;

    @Basic
    @Column(name = "BRANCH_ID", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true, nullable = true)
    private String branchId;

    @Basic
    @Column(name = "BRANCH", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true, nullable = true)
    private String branch;

    @Basic
    @Column(name = "REGION", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true, nullable = true)
    private String region;

    @Basic
    @Column(name = "SITE", nullable = true, insertable = true, updatable = true, length = 2)
    @CobolType(numeric = true, nullable = true)
    private String site;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer that = (Customer) o;
        return Objects.equals(accno, that.accno) &&
                Objects.equals(row, that.row);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accno, row);
    }
}

@Entity
@Table(name = "v_CUSTOMER_PERSON")
@SequenceGenerator(
        name = "CUSTOMER_PERSON_SEQ",
        sequenceName = "CUSTOMER_PERSON_SEQ",
        allocationSize = 1
)
@Getter
@Setter
@ToString
@FieldNameConstants
public class CustomerPerson {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUSTOMER_PERSON_SEQ")
    @Column(name = "NEWLAB_CHRONO", nullable = true, insertable = true, updatable = true, precision = 0)
    @CobolType(numeric = true, nullable = true)
    private Integer newlabChrono;

    @Basic
    @Column(name = "ACCNO", nullable = false, insertable = true, updatable = true, length = 10)
    @CobolType(numeric = true)
    private String accno;

    @Basic
    @Column(name = "ROW", nullable = false, insertable = true, updatable = true, length = 2)
    @CobolType(numeric = true)
    private String row;

    @Basic
    @Column(name = "SHAKHS", nullable = true, insertable = true, updatable = true, length = 1)
    @CobolType(numeric = true)
    private String shakhs;

    @Basic
    @Column(name = "TAR_GAR", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true)
    private String tarGar;

    @Basic
    @Column(name = "SH_NO", nullable = true, insertable = true, updatable = true, length = 12)
    @CobolType(numeric = true)
    private String shNo;

    @Basic
    @Column(name = "BIRTH_DATE", nullable = true, insertable = true, updatable = true, length = 6)
    @CobolType(numeric = true)
    private String birthDate;

    @Basic
    @Column(name = "MAH_COD", nullable = true, insertable = true, updatable = true, length = 3)
    @CobolType(numeric = true)
    private String mahCod;

    @Basic
    @Column(name = "COD_ME", nullable = true, insertable = true, updatable = true, length = 12)
    @CobolType(numeric = true)
    private String codMe;

    @Basic
    @Column(name = "GRP1", nullable = true, insertable = true, updatable = true, length = 3)
    @CobolType(numeric = true)
    private String grp1;

    @Basic
    @Column(name = "BIL1", nullable = true, insertable = true, updatable = true, length = 1)
    @CobolType(numeric = true)
    private String bil1;

    @Basic
    @Column(name = "DUP1", nullable = true, insertable = true, updatable = true, length = 1)
    @CobolType(numeric = true)
    private String dup1;

    @Basic
    @Column(name = "NAME1", nullable = true, insertable = true, updatable = true, length = 60)
    @CobolType(numeric = false)
    private String name1;

    @Basic
    @Column(name = "FAMILI1", nullable = true, insertable = true, updatable = true, length = 80)
    @CobolType(numeric = false)
    private String famili1;

    @Basic
    @Column(name = "PERSON1", nullable = true, insertable = true, updatable = true, length = 1)
    @CobolType(numeric = true)
    private String person1;

    @Basic
    @Column(name = "FATHER", nullable = true, insertable = true, updatable = true, length = 60)
    @CobolType(numeric = false)
    private String father;

    @Basic
    @Column(name = "HOZE", nullable = true, insertable = true, updatable = true, length = 2)
    @CobolType(numeric = true)
    private String hoze;

    @Basic
    @Column(name = "CITY1", nullable = true, insertable = true, updatable = true, length = 40)
    @CobolType(numeric = false)
    private String city1;

    @Basic
    @Column(name = "TEL1", nullable = true, insertable = true, updatable = true, length = 13)
    @CobolType(numeric = true)
    private String tel1;

    @Basic
    @Column(name = "POST1", nullable = true, insertable = true, updatable = true, length = 10)
    @CobolType(numeric = true)
    private String post1;

    @Basic
    @Column(name = "ADDRS1", nullable = true, insertable = true, updatable = true, length = 160)
    @CobolType(numeric = false)
    private String addrs1;

    @Basic
    @Column(name = "E_MAIL", nullable = true, insertable = true, updatable = true, length = 40)
    @CobolType(numeric = false)
    private String eMail;

    @Basic
    @Column(name = "FAX1", nullable = true, insertable = true, updatable = true, length = 13)
    @CobolType(numeric = true)
    private String fax1;

    //other fields...
    
    @Transient
    private Integer isForeign;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CustomerPerson that = (CustomerPerson) o;
        return Objects.equals(accno, that.accno) &&
                Objects.equals(row, that.row);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accno, row);
    }
}

该服务已在@Transactional 的外部服务中调用

@Service
@RequiredArgsConstructor
public class CustomerService {

    @Value("${range.trackingCodeThreadLocalKey}")
    private String trackingCodeKey;
    @Value("${customer.sync.isNewRecord}")
    private String isNewRecordKey;
    private static final Logger log = LoggerFactory.getLogger(CustomerService.class);

    private final CustomerRepository customerRepository;
    private final CustomerPersonRepository customerPersonRepository;
    private final CustomerCompanyRepository customerCompanyRepository;
    private final AccountMapRepository accountMapRepository;
    private final AccountTypeMapRepository accountTypeMapRepository;
    private final CustomerMapper customerMapper;
    private final CompositeCustomerMapper compositeCustomerMapper;
    private final RangeService rangeService;
    private final ThreadLocalUtil threadLocalUtil;

    public String syncAccount(Long newAccountNumber, CustomerAccountResponseDto galaxyData) {
        Optional<AccountMapEntity> optAccountMapEntity = accountMapRepository.findByNewAccountNo(newAccountNumber);
        CustomerDto customerData = new CustomerDto();
        List<CustomerPerson> customerPersonList = null;
        List<Customer> customers = null;
        CustomerCompany customerCompany = null;
        CustomerDto mappedCompositeCustomerPersons;
        boolean updateRecord = false;

        if (optAccountMapEntity.isPresent()) {
            customerData = getCustomerData(optAccountMapEntity.get());
        }

        String legacyAccountNumber = getLegacyAccountNumber(customerData, galaxyData);
        legacyAccountNumber = StringUtil.addLeftLeadingZero(legacyAccountNumber, Constants.Legacy_ACCOUNTNO_MAX);
        log.info("######legacyAccountNumber. {}", legacyAccountNumber);

        if (CustomerUtil.isCompositePerson(galaxyData)) {
            Customer zeroRowCustomer = null;
            CustomerPerson zeroRowCustomerPerson = null;


            if (!ObjectUtils.isEmpty(customerData.getCustomerList()) &&
                    !ObjectUtils.isEmpty(customerData.getCustomerPersonList()) &&
                    customerData.getCustomerList().stream().findFirst().isPresent() &&
                    customerData.getCustomerPersonList().stream().findFirst().isPresent()) {
                updateRecord = true;
                mappedCompositeCustomerPersons = compositeCustomerMapper.compositeInquiryToCustomerDto(galaxyData, customerData);

                if (mappedCompositeCustomerPersons.getCustomerList().stream().findFirst().isPresent())
                    zeroRowCustomer = compositeCustomerMapper.toZeroRowCustomer(galaxyData, mappedCompositeCustomerPersons.getCustomerList().stream().findFirst().get());

                if (mappedCompositeCustomerPersons.getCustomerPersonList().stream().findFirst().isPresent())
                    zeroRowCustomerPerson = compositeCustomerMapper.toZeroRowCustomerPeson(galaxyData, mappedCompositeCustomerPersons.getCustomerPersonList().stream().findFirst().get(), mappedCompositeCustomerPersons.getCustomerPersonList());

                mappedCompositeCustomerPersons.getCustomerList().set(0, zeroRowCustomer);
                mappedCompositeCustomerPersons.getCustomerPersonList().set(0, zeroRowCustomerPerson);

            } else {
                zeroRowCustomer = compositeCustomerMapper.toZeroRowCustomer(galaxyData, new Customer());
                mappedCompositeCustomerPersons = compositeCustomerMapper.compositeInquiryToCustomerDto(galaxyData, null);
                zeroRowCustomerPerson = compositeCustomerMapper.toZeroRowCustomerPeson(galaxyData, new CustomerPerson(), mappedCompositeCustomerPersons.getCustomerPersonList());
                mappedCompositeCustomerPersons.getCustomerList().add(0, zeroRowCustomer);
                mappedCompositeCustomerPersons.getCustomerPersonList().add(0, zeroRowCustomerPerson);
            }

            customers = mappedCompositeCustomerPersons.getCustomerList();
            customerPersonList = mappedCompositeCustomerPersons.getCustomerPersonList();


            if (!ObjectUtils.isEmpty(customers)) {
                for (Customer customer : customers) {
                    customer.setAccno(legacyAccountNumber);
                }
            }
            if (!ObjectUtils.isEmpty(customerPersonList)) {
                for (CustomerPerson customerPerson : customerPersonList) {
                    customerPerson.setAccno(legacyAccountNumber);
                }
            }


        } else if (CustomerUtil.isLegalPerson(galaxyData)) {

            if (!ObjectUtils.isEmpty(customerData.getCustomerList()) &&
                    !ObjectUtils.isEmpty(customerData.getCustomerPersonList()) &&
                    !ObjectUtils.isEmpty(customerData.getCustomerCompany())) {
                updateRecord = true;
                customerPersonList = customerMapper.realPersonToCustomerPersonList(galaxyData, customerData.getCustomerPersonList());
                customerCompany = customerMapper.legalPersonToCustomerCompany(galaxyData, customerData.getCustomerCompany());
                customers = customerMapper.accountToCustomer(galaxyData, customerData.getCustomerList(), customerData.getCustomerPersonList(), customerCompany);

            } else {
                customers = customerMapper.accountToCustomer(galaxyData, new ArrayList<>(), new ArrayList<>(), new CustomerCompany());
                customerPersonList = customerMapper.realPersonToCustomerPersonList(galaxyData, new ArrayList<>());
                customerCompany = customerMapper.legalPersonToCustomerCompany(galaxyData, new CustomerCompany());
            }


            if (!ObjectUtils.isEmpty(customers)) {
                for (Customer customer : customers) {
                    customer.setAccno(legacyAccountNumber);
                }
            }
            if (!ObjectUtils.isEmpty(customerPersonList)) {
                for (CustomerPerson customerPerson : customerPersonList) {
                    customerPerson.setAccno(legacyAccountNumber);
                }
            }
            if (!ObjectUtils.isEmpty(customerCompany)) {
                customerCompany.setAccno(legacyAccountNumber);
            }


        } else if (CustomerUtil.isRealPerson(galaxyData)) {

            if (!ObjectUtils.isEmpty(customerData.getCustomerList()) &&
                    !ObjectUtils.isEmpty(customerData.getCustomerPersonList())) {
                updateRecord = true;
                customerPersonList = customerMapper.realPersonToCustomerPersonList(galaxyData, customerData.getCustomerPersonList());
                customers = customerMapper.accountToCustomer(galaxyData, customerData.getCustomerList(), customerData.getCustomerPersonList(), null);

            } else {
                customers = customerMapper.accountToCustomer(galaxyData, new ArrayList<>(), new ArrayList<>(), null);
                customerPersonList = customerMapper.realPersonToCustomerPersonList(galaxyData, new ArrayList<>());
            }

            if (!ObjectUtils.isEmpty(customers)) {
                for (Customer customer : customers) {
                    customer.setAccno(legacyAccountNumber);
                }
            }
            if (!ObjectUtils.isEmpty(customerPersonList)) {
                for (CustomerPerson customerPerson : customerPersonList) {
                    customerPerson.setAccno(legacyAccountNumber);
                }
            }
        }

        if (!ObjectUtils.isEmpty(threadLocalUtil.getKey(isNewRecordKey)) && (Boolean) threadLocalUtil.getKey(isNewRecordKey))// todo it seems shoule be !isEmpty
            saveAccountMap(newAccountNumber.toString(), legacyAccountNumber);

        saveCustomers(updateRecord, customers, customerPersonList, customerCompany);
        return legacyAccountNumber;
    }

    public void saveAccountMap(String newAccountNumber, String legacyAccountNumber) {
        AccountMapEntity accountMapEntity = new AccountMapEntity();
        accountMapEntity.setNewAccountNo(Long.valueOf(newAccountNumber));
        accountMapEntity.setLegacyAccountNo(Long.valueOf(legacyAccountNumber));
        boolean ifExist = accountMapRepository.existsByNewAccountNoOrLegacyAccountNo(Long.valueOf(newAccountNumber), Long.valueOf(legacyAccountNumber));
        if (!ifExist) accountMapRepository.saveAndFlush(accountMapEntity);
    }


    //todo check below for save and flush of list
    public void saveCustomers(Boolean updateRecord, List<Customer> customers, List<CustomerPerson> customerPersonList, CustomerCompany customerCompany) {
        if (!ObjectUtils.isEmpty(updateRecord) && !ObjectUtils.isEmpty(customers) && !ObjectUtils.isEmpty(customerPersonList)) {

            if (!updateRecord) {
                customerRepository.saveAll(customers);
                customerRepository.flush();
                customerPersonRepository.saveAll(customerPersonList);
                customerPersonRepository.flush();
            } else {
                for (Customer customer : customers) {
                    Optional<Customer> optCustomerById = customerRepository.findById(customer.getNewlabChrono());
                    if (optCustomerById.isPresent()) {
                        Customer customer1 = optCustomerById.get();
                        BeanUtils.copyProperties(customer, customer1);
                        boolean equals = customer1.equals(customer);
                        System.out.println(equals);
                        String s = customer1.toString();
                        customerRepository.saveAndFlush(customer1);
                        log.info("customer updated");
                    }
                }

                 for (CustomerPerson customerPerson : customerPersonList) {
                    CustomerPerson cpSaved = customerPersonRepository.findCustomerPersonByNewlabChrono(customerPerson.getNewlabChrono());
                    BeanUtils.copyProperties(customerPerson, cpSaved);
                    boolean equals = cpSaved.equals(customerPerson);
                    System.out.println(equals);
// ###################
                    customerPersonRepository.saveAndFlush(cpSaved); //Error occurs here
// ###################
                    log.info("customer person updated");
                } 

            }
            if (customerCompany != null)
                customerCompanyRepository.saveAndFlush(customerCompany);

        }
    }

    public CustomerDto getCustomerData(AccountMapEntity accountMapEntity) {
        List<Customer> customerByAccno = customerRepository.findAllByAccountNumber(String.valueOf(accountMapEntity.getLegacyAccountNo()));
        List<CustomerPerson> customerPersonByAccno = customerPersonRepository.findAllByAccountNumber(String.valueOf(accountMapEntity.getLegacyAccountNo()));
        CustomerCompany customerCompanyByAccno = customerCompanyRepository.findByAccountNumber(String.valueOf(accountMapEntity.getLegacyAccountNo()));

        CustomerDto customerDto = new CustomerDto();
        customerDto.setCustomerList(customerByAccno);
        customerDto.setCustomerPersonList(customerPersonByAccno);
        customerDto.setCustomerCompany(customerCompanyByAccno);
        return customerDto;
    }


    private String getLegacyAccountNumber(CustomerDto customerData, CustomerAccountResponseDto galaxyData) {
        String legacyAccountNumber = null;
        if (!ObjectUtils.isEmpty(customerData) && !ObjectUtils.isEmpty(customerData.getCustomerList())) {
            Optional<Customer> optCustomer = customerData.getCustomerList().stream().findFirst();
            if (optCustomer.isPresent()) {
                Customer customer = optCustomer.get();
                legacyAccountNumber = customer.getAccno();
            }
        } else {

            Optional<AccountTypeMap> optAccountTypeMap = accountTypeMapRepository.findByAccountTypeCodeAndAccountSubTypeCode(galaxyData.getAccount().getAccountTypeCode(), galaxyData.getAccount().getAccountSubTypeCode());
            if (optAccountTypeMap.isPresent()) {
                AccountTypeMap accountTypeMap = optAccountTypeMap.get();
                String accountGroup = accountTypeMap.getAccountGroup();
                String branchCode = galaxyData.getAccount().getAccountTypeCode();
                String cbiDb = accountTypeMap.getCbiDb();
                String cbiCr = accountTypeMap.getCbiCr();
                String cbkDb = accountTypeMap.getCbkDb();
                String cbkCr = accountTypeMap.getCbkCr();
                GenerateAccountNumberResponse response = rangeService.generateAccountNumber(branchCode, accountGroup, cbiDb, cbiCr, "  25E", "  60A");
                legacyAccountNumber = response.getResponse().getAccountNo().toString();
                threadLocalUtil.addKey(trackingCodeKey, response.getResponse().getTrackingCode());
                threadLocalUtil.addKey(isNewRecordKey, true);
            }

        }
        log.warn("#########  legacyAccountNumber {}", legacyAccountNumber);

        return legacyAccountNumber;
    }
}

当我调试或运行应用程序时,Customer 可以更新,但是当我想更新 CustomerPerson 时,它会在 PK 上抛出 ConstraintViolationException 以更新实体。有什么建议吗?我认为它与equals and hashCodes 有一些关系,但我写的equals and hashCodesCustomer 相同。

外部服务是 SyncLegacyAccountServiceImpl

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class SyncLegacyAccountServiceImpl implements ISyncLegacyAccountService {

    private static final Logger log = LoggerFactory.getLogger(GalaxyService.class);

    @Value("${range.trackingCodeThreadLocalKey}")
    private String trackingCodeKey;
    @Value("${customer.sync.isNewRecord}")
    private String isNewRecordKey;

    private final IMQService iMQService;
    private final IAccountRequestService iAccountRequestService;
    private final CustomerService customerService;
    private final GalaxyService galaxyService;
    private final RangeService rangeService;
    private final ThreadLocalUtil threadLocalUtil;

    @Override
    @Transactional
    public void handleSyncRequest(Event event) {
        try {
            rangeCompensation();
            Long newAccountNumber = Long.valueOf(event.getArgument().get(Constants.KEY_ACCOUNT_NO_MQ).toString());
            CustomerAccountResponseDto galaxyData = galaxyService.getGalaxyData(String.valueOf(newAccountNumber));
            String legacyAccountNumber = customerService.syncAccount(newAccountNumber, galaxyData);
            log.info("legacy no {}",legacyAccountNumber);
            iMQService.send(MQUtil.buildAccountChangeResponse(null, legacyAccountNumber, event.getMessageId()));
            iAccountRequestService.saveSuccessfulAccountRequest(event);
            log.info("saved succed");
            updateRangeToFinal();
            log.info("updateRangeToFinal");
        } catch (Exception exception) {
            log.error(exception.toString());
            updateRangeToRevoke();
        }
    }

    private void updateRangeToFinal() {
        Boolean isNewRecord = (Boolean) threadLocalUtil.getKey(isNewRecordKey);
        if (!ObjectUtils.isEmpty(isNewRecord)) {
            if (isNewRecord) {
                rangeService.updateToFinal(String.valueOf(threadLocalUtil.getKey(trackingCodeKey)));
                removeFromThreadLocal(trackingCodeKey);
                removeFromThreadLocal(isNewRecordKey);
            }
        }
    }

    private void updateRangeToRevoke() {
        Boolean isNewRecord = (Boolean) threadLocalUtil.getKey(isNewRecordKey);
        if (!ObjectUtils.isEmpty(isNewRecord)) {
            if (isNewRecord) {
                rangeService.updateToRevoke(String.valueOf(threadLocalUtil.getKey(trackingCodeKey)));
                removeFromThreadLocal(trackingCodeKey);
                removeFromThreadLocal(isNewRecordKey);
            }
        }
    }

    private void rangeCompensation() {
        if (!ObjectUtils.isEmpty(threadLocalUtil.getKey(trackingCodeKey)) && !ObjectUtils.isEmpty(threadLocalUtil.getKey(isNewRecordKey))) {
            updateRangeToRevoke();
        }
    }

    private void removeFromThreadLocal(String key) {
        threadLocalUtil.removeKey(key);
    }

日志

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [SGB.C_PR_PK]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

我知道在这种情况下 ViolationException 是什么。但这很奇怪,因为以同样的方式,Customer 实体会正确更新。但是当它想要更新 CustomerPerson 时,它会抛出这个异常。我检查了equals 方法以确保更新的对象与 Db 对象相同(ID-->newlabChrono)。

【问题讨论】:

  • A) 请在代码中指定发生错误的行,B) 请粘贴完整的堆栈跟踪,C) 如有必要,请查看休眠日志(启用调试),并粘贴 SQL 查询这个给您带来问题的特定请求。
  • 对于A,我写了发生错误的那一行。但是这里不支持行号:(。customerPersonRepository.saveAndFlush(cpSaved); //这里发生错误
  • 我更新了帖子。
  • 您是自己创建表还是 JPA?如果您自己,请出示 SQL 代码,我们需要看看是什么决定了您的 CustomerPerson 表与 Customer 的 PK。
  • 其实是一个视图,不是我创建的。

标签: java spring spring-boot spring-data-jpa spring-data


【解决方案1】:

DataIntegrityViolationException 表示您的代码尝试以数据库方案禁止的方式修改数据库。缩写“PK”通常表示“主键”,因此您的代码可能试图插入具有重复 ID 的行。

【讨论】:

  • 我知道在这种情况下 ViolationException 是什么。但这很奇怪,因为以同样的方式,Customer 实体会正确更新。但是当它想要更新 CustomerPerson 时,它会抛出这个异常。我检查了equals 方法以确保更新的对象与 Db 相同(ID-->newlabChrono)。
  • 好吧,如果它是一样的,你为什么INSERT它而不是UPDATEing它。
  • 当使用repository.save();或者更好的说使用Spring Data JPA时,save的保存或更新方法没有区别。
  • 由于错误来自数据库,我将查看 JPA 提供程序为您的案例生成的 SQL,并确定它是否符合您的期望。如果可以的话,我会尝试在数据库中手动调试它;否则我会尝试看看为什么 SQL 是错误的。
【解决方案2】:

这里只是猜测,但可能发生的情况如下:

CustomerPerson cpSaved = customerPersonRepository.findCustomerPersonByNewlabChrono(customerPerson.getNewlabChrono()); 

检索 ID=XX 的特定 CustomPerson

BeanUtils.copyProperties(customerPerson, cpSaved); 

cpSaved (ID) 正在被此方法替换为可能 ID=YY

customerPersonRepository.saveAndFlush(cpSaved); //此处发生错误,(ID) 现在是 YY 但已经存在,它实际上是在尝试创建一个新的 OBJECT,而不是更新实体。

【讨论】:

  • 我也查了equals and hashCodeBeanUtils前后的ID和之前一样。
猜你喜欢
  • 2015-06-25
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
  • 2019-07-24
  • 2021-09-06
  • 1970-01-01
相关资源
最近更新 更多