Я пытаюсь вставить 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();
}
}