IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

Persistance en cascade


Sujet :

JPA Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mars 2003
    Messages
    78
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 78
    Par défaut Persistance en cascade
    Bonjour,

    Je recontre des problème lors de la création d'enregistrements avec des EJB3.0+JPA.

    Description:
    Une entité A a pour attribut un set d'entité B.
    L'entité B est un objet qui mappe une table d'association entre la table A(mappée par l'objet A) et la table C(mappée par l'objet C).

    Lorsque je veux persister une entité A j'obtiens le message d'erreur suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    org.apache.openjpa.lib.jdbc.ReportingSQLException: [BEA][Oracle JDBC Driver][Oracle]ORA-02291: integrity constraint (FK_B_A) violated - parent key not found
    L'enregistrement dans la table B ne passe pas car il ne détecte pas que le parent A a été créé comme si les deux inserts se faisaient dans des transactions différentes.

    Merci pour votre aide.

  2. #2
    mow
    mow est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 210
    Par défaut
    Salut,

    Je n'ai peut être pas la solution mais ci-dessous quelques pistes de recherche :

    1) Les 2 transactions ont-elles lieu dans la même session factory ?

    2) es-tu sûr que ton mapping est bien fait ? Pour vérifier, insère toi même des données dans tes tables A et B et vérifie si tu les récupères dans ton application...

    Bon courage,
    Mow

  3. #3
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Une entité A a pour attribut un set d'entité B.
    L'entité B est un objet qui mappe une table d'association entre la table A(mappée par l'objet A) et la table C(mappée par l'objet C).
    ....

    Si je comprends bien, si tu ajoutes un B à l'attribut Set de A tu obtiens cette erreur ?
    Comment tu as déclaré la relation entre A et B ? est elle bi-diréctionnelle ou pas ? dans quel ordre tu persistes tes données ?
    Bref, quelques extraits de code s'il te plaît.

  4. #4
    Membre confirmé
    Inscrit en
    Mars 2003
    Messages
    78
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 78
    Par défaut
    C'est parti pour le code.

    Classe A(ProductList):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class ProductList implements java.io.Serializable {
    ...
    private Set<TfcList> tfcLists = new HashSet<TfcList>(0);
    ...
    	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "productList")
    	public Set<TfcList> getTfcLists() {
    		return this.tfcLists;
    	}
     
    	public void setTfcLists(Set<TfcList> tfcLists) {
    		this.tfcLists = tfcLists;
    	}
    ...
    Classe B(TfcList) qui est une classe d'association
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    public class TfcList implements java.io.Serializable {
    ...
    	private TfcListId id;
    	private ProductList productList;
    	private Tfc tfc;
    ...
    	@EmbeddedId
    	@AttributeOverrides( {
    			@AttributeOverride(name = "productListId", column = @Column(name = "PRODUCT_LIST_ID", unique = false, nullable = false, insertable = true, updatable = true, precision = 8, scale = 0)),
    			@AttributeOverride(name = "tfcId", column = @Column(name = "TFC_ID", unique = false, nullable = false, insertable = true, updatable = true, precision = 8, scale = 0)) })
    	public TfcListId getId() {
    		return this.id;
    	}
     
    	public void setId(TfcListId id) {
    		this.id = id;
    	}
     
    	@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
    	@JoinColumn(name = "PRODUCT_LIST_ID", unique = false, nullable = false, insertable = false, updatable = false)
    	public ProductList getProductList() {
    		return this.productList;
    	}
     
    	public void setProductList(ProductList productList) {
    		this.productList = productList;
    	}
     
    	@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
    	@JoinColumn(name = "TFC_ID", unique = false, nullable = false, insertable = false, updatable = false)
    	public Tfc getTfc() {
    		return this.tfc;
    	}
     
    	public void setTfc(Tfc tfc) {
    		this.tfc = tfc;
    	}
    ...
    Code de l'ejb de création:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ProductList transientInstance = new ProductList();
    Set<TfcList> tfcLists = new HashSet<TfcList>(0);
    /*Alimentation de la liste
    Code d'alimentation
    */
    transientInstance.setTfcLists(tfcLists);
    entityManager.persist(transientInstance);
    Je précise qu'en consultation cela fonctionne.

  5. #5
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    J'ai comme l'impression que le dernier bout de code (le plus intéressant) n'est pas complet.
    Mais en tout cas, il ne fait pas ecraser le champ de type Set de ProductList : .
    Il faut plutôt y aller par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    transientInstance.getTfcLists().addAll(tfcLists);
    Cette règle est générale. Il faut instancier la collection dans le constructeur et ne plus écraser cete instance, mais plutôt la modifier.

    Sinon, dans le code d'alimentation, t'es sur d'avoir assigné le champ ProductList de toutes les instances de transientInstance ? Normalement, c'est ça la cause de tes problèmes.

    De plus, pour pouvoir faire ça, il te faut d'abord persister le type parent avant de spécifier ses fils, sinon, les fils pointeront vers un parent non persisté.

    Je sais que j'explique comme une patate, voici donc un petit exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    ProductList transientInstance = new ProductList();
     
    entityManager.persist(transientInstance);//<-Premier ajout
     
    /*Alimentation de la liste
    */
    TfcList x1 = new TfcList();
    x1.setProductList(transientInstance);//<-Très important: faire pointer le fils vers le parent
     
    transientInstance.getTfcLists().add(x1);
     
    //de même pour les autres instances de TfcList
    entityManager.persist(transientInstance);
    En espérant que ce soit utile.
    Bonne chance.

  6. #6
    Membre confirmé
    Inscrit en
    Mars 2003
    Messages
    78
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 78
    Par défaut
    Tout d'abord merci pour ces conseils.

    Citation Envoyé par djo.mos Voir le message
    ...Sinon, dans le code d'alimentation, t'es sur d'avoir assigné le champ ProductList de toutes les instances de transientInstance ? Normalement, c'est ça la cause de tes problèmes...
    Tu peux préciser stp, je ne vois pas ce que tu veux dire.

  7. #7
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Bonjour.
    En fait, il aurait suffit que tu ailles plus loin dans ma réponse jusqu'au bout de code
    Il s'agit exactement de la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x1.setProductList(transientInstance);//<-Très important: faire pointer le fils vers le parent
    Pour résumer, voici ce qu'il faut faire pour lier une entité fille B à une entité parente A:
    Persister A.
    Faire le lien de B vers A (b.setParent(A))
    Persister B
    Ajouter B à l'ensemble des fils de A (a.getFils().add(b) ). Si on a Cascade Persist, alors l'étape précédente devient inutile, voire source de problèmes.

    Bonne chance.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Persistance en cascade complexe
    Par mort87 dans le forum JPA
    Réponses: 1
    Dernier message: 03/01/2014, 11h42
  2. [2.x] Persist entité cascade et postPersist
    Par Issiel dans le forum Symfony
    Réponses: 4
    Dernier message: 01/07/2013, 18h33
  3. Réponses: 2
    Dernier message: 12/03/2010, 17h10
  4. Réponses: 2
    Dernier message: 29/04/2009, 19h58
  5. Persist en cascade
    Par stylatone dans le forum Hibernate
    Réponses: 2
    Dernier message: 02/02/2008, 14h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo