случайное ограничение поведения - PullRequest
0 голосов
/ 19 января 2020

Я пытаюсь вставить 1 значение в таблицу 'beleg_kopf', затем вставить 1 значение в 'beleg_kunden' и затем вставить значения от 1 до n в 'beleg_positionen'. Внешние ключи можно увидеть в коде SQL. Когда мой P C работает нормально быстро, вставка всегда завершается неудачей из-за сбоя ограничения внешнего ключа. Но когда мой P C очень медленный, он работает правильно.

Эта ошибка просто al ie, поскольку строки вставляются в неправильном порядке и когда P C настолько медленный, что каждый INSERT принимает через полминуты следующая INSERT распознает уже существующую строку в предыдущей таблице. Но при нормальной скорости выполнения Hibernate забывает, что значение уже существует.

Проблема почти невозможна для восстановления, и она возникает совершенно случайно.

Сообщение об ошибке:

MySQLIntegrityConstraintViolationException: Невозможно добавить или обновить дочернюю строку: сбой ограничения внешнего ключа (beleg_kunden, CONSTRAINT bkd_belegnr ИНОСТРАННЫЙ КЛЮЧ (belegnr) ССЫЛКИ beleg_kopf (belegnr) ON UPDATE CASCADE)

SQL DDL:

CREATE TABLE IF NOT EXISTS `beleg_kopf` (
  `belegnr` INT(8) NOT NULL AUTO_INCREMENT,
  `auftrag` INT(9) NOT NULL,
  `typ` VARCHAR(1) NOT NULL,
  `datum` DATE NOT NULL,
  `payterms` INT(2) NULL,
  PRIMARY KEY (`belegnr`)
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `beleg_kunden` (
  `belegnr` INT(8) NOT NULL,
  `kdnr` INT(5) NOT NULL,
  `typ` INT(2) NOT NULL,
  `name` VARCHAR(80) NOT NULL,
  `vorname` VARCHAR(80) NULL,
  `strasse` VARCHAR(80) NULL,
  `hausnr` VARCHAR(15) NULL,
  `adresse2` VARCHAR(80) NULL,
  `plz` VARCHAR(10) NOT NULL,
  `ort` VARCHAR(80) NOT NULL,
  `land` INT(3) NOT NULL,
  `uid` VARCHAR(30) NULL,
  PRIMARY KEY (`belegnr`),
  CONSTRAINT `bkd_belegnr`
    FOREIGN KEY (`belegnr`)
    REFERENCES `beleg_kopf` (`belegnr`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `beleg_positionen` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `belegnr` INT(8) NOT NULL,
  `anzahl` DECIMAL(7,2) UNSIGNED NOT NULL,
  `einheit` VARCHAR(15) NULL,
  `bezeichnung` VARCHAR(200) NOT NULL,
  `preis` DECIMAL(8,2) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `bpos_belegnr_idx` (`belegnr` ASC),
  CONSTRAINT `bpos_belegnr`
    FOREIGN KEY (`belegnr`)
    REFERENCES `beleg_kopf` (`belegnr`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE)
ENGINE = InnoDB;

Код гибернации:

@Entity
@Table(name="beleg_kopf")
@SequenceGenerator(name="belegnr", initialValue = 1, allocationSize = 1)
public class BelegKopf implements BaseDTO {
    @Id
    @Column(name="belegnr", nullable = false, length = 8)
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int belegnr;

    @Column(name="auftrag", nullable = false, length = 9)
    private int auftrag;

    @Column(name="typ", nullable = false, length = 2)
    private char typ;

    @Column(name="datum", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date datum;

    @Column(name="payterms", nullable = true, length = 2)
    private int payterms;

    ...
}

@Entity
@Table(name="beleg_kunden")
public class BelegKunde implements BaseDTO {
    @Id
    @Column(name="belegnr", nullable = false, length = 8)
    private int belegnr;

    @Column(name="kdnr", nullable = false, length = 5)
    private int kdnr;

    @Column(name="typ", nullable = false, length = 2)
    private int typ;

    @Column(name="name", nullable = false, length = 80)
    private String name;

    @Column(name="vorname", nullable = true, length = 80)
    private String vorname;

    @Column(name="strasse", nullable = true, length = 80)
    private String strasse;

    @Column(name="hausnr", nullable = true, length = 15)
    private String hausnr;

    @Column(name="adresse2", nullable = true, length = 80)
    private String adresse2;

    @Column(name="plz", nullable = false, length = 10)
    private String plz;

    @Column(name="ort", nullable = false, length = 80)
    private String ort;

    @Column(name="land", nullable = false, length = 3)
    private int land;

    @Column(name="uid", nullable = true, length = 30)
    private String uid;

    ...
}

@Entity
@Table(name="beleg_positionen")
@SequenceGenerator(name="id", initialValue = 1, allocationSize = 1)
public class BelegPosition implements BaseDTO {
    @Id
    @Column(name="id", nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @Column(name="belegnr", nullable = false, length = 8)
    private int belegnr;

    @Column(name="anzahl", nullable = false, length = 7, precision = 2)
    private double anzahl;

    @Column(name="einheit", nullable = true, length = 15)
    private String einheit;

    @Column(name="bezeichnung", nullable = false, length = 200)
    private String bezeichnung;

    @Column(name="preis", nullable = false, length = 8, precision = 2)
    private double preis;

    ...
}

Код вставки Hibernate:

public static void createBeleg(BelegKopf kopf, BelegKunde kunde, List<BelegPosition> pos) throws DatabaseException {
    Session hsession = null;
    Transaction htransaction = null;

    try {
        hsession = HibernateUtil.getSessionFactory().openSession();
        htransaction = hsession.beginTransaction();

        hsession.save(kopf);
        hsession.save(kunde);

        for (BelegPosition p : pos)
            hsession.save(p);

        htransaction.commit();
    } catch (HibernateException ex) {
        if (htransaction != null)
            htransaction.rollback();

        throw new DatabaseException(ex);
    } finally {
        if (hsession != null)
            hsession.close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...