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

marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Dernière intervention
26 mars 2012
- 25 mars 2012 à 14:40 - Dernière réponse : marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
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 

Votre réponse

5 réponses

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


par
@MapsId("aIda")

Merci marwen109 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 86 internautes ce mois-ci

Commenter la réponse de marwen109
marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Dernière intervention
26 mars 2012
- 25 mars 2012 à 20:30
0
Merci
pas de réponse
Commenter la réponse de marwen109
cs_Julien39
Messages postés
6450
Date d'inscription
mardi 8 mars 2005
Dernière intervention
17 mai 2018
- 26 mars 2012 à 08:15
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
marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Dernière intervention
26 mars 2012
- 26 mars 2012 à 14:40
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
marwen109
Messages postés
64
Date d'inscription
jeudi 12 août 2010
Dernière intervention
26 mars 2012
- 26 mars 2012 à 14:51
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

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.