sql >> Databáze >  >> RDS >> Mysql

JPA vložit výsledky nadřazené/podřízené do MySQLIntegrityConstraintViolationException

Váš vztah nemusí být obousměrný. Zde v komentářích jsou nějaké dezinformace.

Také jste řekli, že jste přidali pole „parentId“ do entity Child, protože jste předpokládali, že JPA potřebuje „vědět“ o nadřazeném poli, aby mohl nastavit hodnotu. Problém není v tom, že by JPA na základě anotací, které jste poskytli, o daném oboru nevěděl. Problém je v tom, že jste poskytli "příliš mnoho" informací o poli, ale tyto informace nejsou vnitřně konzistentní.

Změňte pole a anotaci v nadřazeném prvku na:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id")
private List<Child> children;

Poté zcela odstraňte „parentId“ z entity Child. Dříve jste zadali anotaci JoinTable. Nicméně to, co chcete, není JoinTable. JoinTable by vytvořila další třetí tabulku za účelem vzájemného propojení těchto dvou entit. To, co chcete, je pouze JoinColumn. Jakmile přidáte anotaci JoinColumn do pole, které je také anotováno pomocí OneToMany, vaše implementace JPA bude vědět, že přidáváte FK do tabulky CHILD. Problém je v tom, že JPA má tabulku CHILD již definovanou se sloupcem parent_id.

Myslete na to, že tomu dáváte dvě protichůdné definice funkce tabulky CHILD a sloupce parent_id. V jednom případě jste vám JPA řekli, že je to entita a parent_id je prostě hodnota v této entitě. Ve druhém jste JPA řekli, že vaše tabulka CHILD není entita, ale používá se k vytvoření vztahu cizího klíče mezi vaší tabulkou CHILD a PARENT. Problém je v tom, že vaše tabulka CHILD již existuje. Když pak svou entitu zachováváte, řekli jste jí, že parent_id je explicitně null (není nastaveno), ale pak jste jí také řekli, že vaše parent_id by mělo být aktualizováno, aby nastavilo odkaz na cizí klíč na nadřazenou tabulku.

Upravil jsem váš kód pomocí změn, které jsem popsal výše, a také jsem nazval „přetrvávat“ místo „sloučit“.

Výsledkem byly 3 SQL dotazy

insert into PARENT (ID) values (default)
insert into CHILD (ID) values (default)
update CHILD set parent_id=? where ID=?

To dokonale odráží to, co chcete. Položka PARENT je vytvořena. Vytvoří se položka CHILD a poté se aktualizuje záznam CHILD, aby správně nastavil cizí klíč.

Pokud místo toho přidáte anotaci

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id", nullable = false)
private List<Child> children;

Poté spustí následující dotaz, když vloží potomka

insert into CHILD (ID, parent_id) values (default, ?)

tedy správně nastavit váš FK od samého začátku.



  1. Jak zlepšit výkon pro databázi SQLite pro Android

  2. Provozování datového skladu na PostgreSQL

  3. Získání připojení PHP PDO z mysql_connect()?

  4. Optimalizace Mysql pro REGEXP