Spring 宠物诊所:尝试删除具有访问外键的兽医时出现BatchError

z31licg0  于 2023-01-29  发布在  Spring
关注(0)|答案(1)|浏览(120)

我得到了一个任务来扩展SPRING petclinic应用程序(派生自此回购协议:https://github.com/spring-petclinic/spring-petclinic-rest)。一个任务是“显示兽医的所有访问”。
为此,我在hsqldb的表visits中添加了一个外键和一个列:

...
CREATE TABLE visits (
  id          INTEGER IDENTITY PRIMARY KEY,
  pet_id      INTEGER NOT NULL,
  vet_id      INTEGER NOT NULL,
  visit_date  DATE,
  description VARCHAR(255)
);

ALTER TABLE visits ADD CONSTRAINT fk_visits_vets FOREIGN KEY (vet_id) REFERENCES vets (id);
ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id);
CREATE INDEX visits_pet_id ON visits (pet_id);
...

相应地编辑了visit模型:

@Entity
@Table(name = "visits")
public class Visit extends BaseEntity {
...
    @ManyToOne
    @JoinColumn(name = "vet_id", referencedColumnName = "id", nullable = false)
    private Vet vet;
...

并将vetId添加到openapi.yml中的#/components/schemas/Visit

Visit:
      title: Visit
      description: A booking for a vet visit.
      allOf:
        - $ref: '#/components/schemas/VisitFields'
        - type: object
          properties:
            id:
              title: ID
              description: The ID of the visit.
              type: integer
              format: int32
              minimum: 0
              example: 1
              readOnly: true
            petId:
              title: Pet ID
              description: The ID of the pet.
              type: integer
              format: int32
              minimum: 0
              example: 1
              readOnly: true
            vetId:
              title: Vet ID
              description: The ID of the veterinarian.
              type: integer
              format: int32
              minimum: 0
              example: 1
              readOnly: true
          required:
            - id
            - vetId
            - petId

我可以构建和运行该项目,但当我尝试删除vet时,我收到以下错误消息:

{
  "className": "org.springframework.dao.DataIntegrityViolationException",
  "exMessage": "could not execute statement; SQL [n/a]; constraint [FK_VISITS_VETS]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
}

因此,我尝试覆盖从Vet生成的delete方法,以首先删除所有对应的Visit,然后删除Vet

public class SpringDataVetRepositoryImpl implements VetRepositoryOverride {
    @PersistenceContext
    private EntityManager em;

    @Override
    public void delete(Vet vet) {
        Integer vetId = vet.getId();
        this.em.createQuery("DELETE FROM Visit visit WHERE vet_id=" + vet.getId()).executeUpdate();
        this.em.createQuery("DELETE FROM Vet vet WHERE id=" + vet.getId()).executeUpdate();
        if (em.contains(vet)) {
            em.remove(vet);
        }
    }
}

但是当我现在运行它时,我得到了一个错误,我不明白,也不知道它可能意味着什么:

{
  "className": "org.springframework.orm.ObjectOptimisticLockingFailureException",
  "exMessage": "Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: delete from vets where id=?; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: delete from vets where id=?"
}

vetvisits都没有被删除。有人知道为什么吗?我当前的项目状态可以在这里找到:https://github.com/Fabian-Anna/java-petclinic/tree/user-story-2

vybvopom

vybvopom1#

引用vets表的外键可防止删除该表中从访视表引用的任何行。
您可以使用ON DELETE CASCASE定义外键,如果删除vets表中的一行,则会导致删除所有参考访视。
请参见www.example.comhttp://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html#dbc_constraints
顺便说一句,你不需要在访问表上创建索引。外键创建自己的索引。

相关问题