Problème d'insertion cascade avec JPA/TopLink [Résolu]

Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
- - Dernière réponse : marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
- 26 mars 2012 à 23:45
Bonjour a tous,
j'ai deux tables A et B comme suit:
CREATE TABLE A (
idA INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
PRIMARY KEY(idA)
);

CREATE TABLE B (
idB VARCHAR(20) NOT NULL,
A_idA INTEGER UNSIGNED NOT NULL,
name VARCHAR(30) NOT NULL,
PRIMARY KEY(idB, A_idA),
FOREIGN KEY(A_idA)
REFERENCES A(idA)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);



deux entités A.java et B.java :

A.java :
public class A implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name "IDA", nullable false)
private Integer ida;
@Basic(optional = false)
@Column(name "NAME", nullable false, length = 30)
private String name;
@OneToMany(cascade CascadeType.ALL, mappedBy "a")
private List bList;
//getters setters
}



BPK.java:

@Embeddable
public class BPK implements Serializable {
@Basic(optional = false)
@Column(name "IDB", nullable false, length = 20)
private String idb;
@Basic(optional = false)
@Column(name "A_IDA", nullable false)
private int aIda;

public BPK() {
}

public BPK(String idb, int aIda) {
this.idb = idb;
this.aIda = aIda;
}
//getters setters
}


B.java:
public class B implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected BPK bPK;
@Basic(optional = false)
@Column(name "NAME", nullable false, length = 30)
private String name;
@JoinColumn(name "A_IDA", referencedColumnName "IDA", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false)
private A a;
//getters setters
}




lorsque j'essaye d'inserer des lignes :
EntityManagerFactory emf=Persistence.createEntityManagerFactory("threadPU");
EntityManager em=emf.createEntityManager();

A a=new A(null,"name1");

java.util.List lB=new ArrayList();

BPK bpk1 =new BPK();
bpk1.setIdb("idB1");
BPK bpk2 =new BPK();
bpk1.setIdb("idB2");
BPK bpk3 =new BPK();
bpk1.setIdb("idB3");

B b1=new B(bpk1,"name1");
B b2=new B(bpk2,"name2");
B b3=new B(bpk3,"name3");

b1.setA(a);
b2.setA(a);
b3.setA(a);

lB.add(b1);
lB.add(b2);
lB.add(b3);

a.setBList(lB);


em.getTransaction().begin();
em.persist(a);
em.getTransaction().commit();



j'ai l'erreur suivante :
Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
Afficher la suite 

5 réponses

Meilleure réponse
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
3
Merci
Enfin ,
simplement :
remplacer :
 @JoinColumn(name "A_IDA", referencedColumnName "IDA", nullable = false, insertable = false, updatable = false)


par
@MapsId("aIda")

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 186 internautes nous ont dit merci ce mois-ci

Commenter la réponse de marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
0
Merci
pas de réponse
Commenter la réponse de marwen109
Messages postés
6413
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
17 mai 2018
246
0
Merci
Bonjour,

Tu essayes d'insérer dans la table B un ligne de données qui fait référence à la table A et l'enregistrement n'est pas encore ajouté dans la table A.

Il faut d'abord ajouter l'id dans la table A avant de l'ajouter dans la table B.
Commenter la réponse de cs_Julien39
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
0
Merci
Merci Julien pour la réponse,
voici une nouvelle version plus propre :

...
public class A implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name "IDA", nullable false)
private Integer ida;
@Basic(optional = false)
@Column(name "NAME", nullable false, length = 30)
private String name;
@OneToMany(cascade CascadeType.ALL, mappedBy "a")
private List bList=new ArrayList();

public void addB(B bp){
bp.setA(this);
bList.add(bp);
}
...


B.java:
...
public class B implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected BPK bPK;
@Basic(optional = false)
@Column(name "NAME", nullable false, length = 30)
private String name;
@JoinColumn(name "A_IDA", referencedColumnName "IDA", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false)
private A a;
...


le code de la class main:
  A a=new A(null,"A1");
   BPK bpk=new BPK();
   bpk.setIdb("b1");
   a.addB(new B(bpk,"B1"));

   EntityManager em=getEntityManager();
   em.getTransaction().begin();
   em.persist(a);
   em.getTransaction().commit();
Commenter la réponse de marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Statut
Membre
Dernière intervention
26 mars 2012
0
Merci
Il faut d'abord ajouter l'id dans la table A avant de l'ajouter dans la table B.


oui je sait , il ya un problème de contrainte d’intégrité référentielle, mais il ne faut pas oublier que je travail avec JPA comme ORM , normalement il se charge lui même de trier l'ordre d'insertion...
j'ai déja travaillé avec une relation 1..N avec ce code SQL et ça marche :
CREATE TABLE parent (
  idparent INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(30) NOT NULL,
  PRIMARY KEY(idparent)
);

CREATE TABLE child (
  idchild INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  parent_idparent INTEGER UNSIGNED NOT NULL,
  name VARCHAR(30) NOT NULL,
  PRIMARY KEY(idchild),
  FOREIGN KEY(parent_idparent)
    REFERENCES parent(idparent)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION
);




lorsque je fait em.persist(parent) l'objet parent est inserée dans la BD avec tous ces Childs automatiquement(cascade), il suffit d'indiquer a l'objet parent qu'il est "lié" a une liste des Childs...

le problème peut-être viens du fait que j'utilise un clé composite(BPK) , je suis complètement bloquée...
Commenter la réponse de marwen109