PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 16/05/2012 10:39:11

zero.h
Membre

MySQL--->Postgres (Jpa)( la valeur d'une clé dupliquée rompt la contr)

Bonjour,
j'essaye de faire une migration de donnees de MySQL vers Postgres et pour cela j'utilise la couche Jpa avec Eclipselink ,la procedure est de lire les donnees à travers la premiere couche qui est celle de MySQL et les mettre à travers l'autre couche qui est en liaison avec Postgres,j'ai fait une classe Converter pour faire la conversion des donnes


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.sensoredabmigration.application;

import java.lang.reflect.*;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
*
*/
public class Converter<S, D> {

    public Converter() {
    }

    /**
     * Returns the getter method
     * @param attribute
     * @return
     */
    private String getGetterMethod(final Field attribute) {
        final String first = attribute.getName().substring(0, 1).toUpperCase();
        final String next = attribute.getName().substring(1, attribute.getName().length()).toLowerCase();
        return "get" + first + next;
    }

    /**
     * Returns the getter method
     * @param attribute
     * @return
     */
    private String getSetterMethod(final Field attribute) {
        final String first = attribute.getName().substring(0, 1).toUpperCase();
        final String next = attribute.getName().substring(1, attribute.getName().length()).toLowerCase();
        return "set" + first + next;
    }

    public List<D> convert(final Class sourceClass, final Class destinationClass, final List<S> listOfSource) {

        final List<D> listOfDestinations = new ArrayList<D>();
        final Field[] attributesSource = sourceClass.getDeclaredFields();

        try {
            for (Iterator<S> it = listOfSource.iterator(); it.hasNext(); ) {
                final S currentSource = it.next();
                final Object currentDestination = destinationClass.newInstance();

                for (int i = 0; i < attributesSource.length; i++) {
                    final Field currentAttribute = attributesSource[ i ];
                    final String getter = getGetterMethod(currentAttribute);
                    final String setter = getSetterMethod(currentAttribute);

                    try {
                        final Method getterMethod = sourceClass.getMethod(getter, null);
                        final S resultGetter = (S) getterMethod.invoke(currentSource, null);

                        Class[] parametres = new Class[1];
                        parametres[0] = (Class) currentAttribute.getGenericType();

                        final Method setterMethod = destinationClass.getMethod(setter, parametres);
                        final D resultSetter = (D) setterMethod.invoke(currentDestination, resultGetter);
                    } catch (NoSuchMethodException exception) {
                        continue;

                    }

                }
                listOfDestinations.add((D) currentDestination);
            }


        } catch (IllegalArgumentException ex) {
            Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
        }
        return listOfDestinations;
    }
}


dans mes entity j'utilise pas le "GeneratedValue" car j'ai deja les donnes dans l'autre base et je veux garder les meme id
voici un bout de code d'une Entity



@Entity
@Table(name = "type_sensoriel")
@NamedQueries({
    @NamedQuery(name = "DestinationTypeSensoriel.findAll", query = "SELECT s FROM DestinationTypeSensoriel s"),
    @NamedQuery(name = "DestinationTypeSensoriel.findById", query = "SELECT s FROM DestinationTypeSensoriel s WHERE s.id = :id"),
    @NamedQuery(name = "DestinationTypeSensoriel.findByNom", query = "SELECT s FROM DestinationTypeSensoriel s WHERE s.nom = :nom")})
public class DestinationTypeSensoriel implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "nom")
    private String nom;

    public DestinationTypeSensoriel() {
    }


et là voici un bout de code pour ma classe main pour une seule table


       //TypeSensoriel
        final SourceTypeSensorielJpaController controllerSourceTypeSensoriel = new SourceTypeSensorielJpaController();
        final DestinationTypeSensorielJpaController controllerDestinationTypeSensoriel = new DestinationTypeSensorielJpaController();
        final List<SourceTypeSensoriel> listeSourceTypeSensoriel = controllerSourceTypeSensoriel.lecture();

        final Converter<SourceTypeSensoriel, DestinationTypeSensoriel> converterTypeSensoriel = new Converter<SourceTypeSensoriel, DestinationTypeSensoriel>();
        final List<DestinationTypeSensoriel> allSourcesTypeSensoriel = converterTypeSensoriel.convert(SourceTypeSensoriel.class, DestinationTypeSensoriel.class, listeSourceTypeSensoriel);

        for (DestinationTypeSensoriel c : allSourcesTypeSensoriel) {

            controllerDestinationTypeSensoriel.create(c);

        }

mon erreur est le suivant
Internal Exception: org.postgresql.util.PSQLException: ERREUR: la valeur d'une clé dupliquée rompt la contrainte unique « type_sensoriel_pkey »
  Détail : La clé « (id)=(1) » existe déjà.
Error Code: 0
Call: INSERT INTO type_sensoriel (id, nom) VALUES (?, ?)
        bind => [1, Profil]

merci d'avance

Hors ligne

#2 16/05/2012 11:49:05

rjuju
Administrateur

Re : MySQL--->Postgres (Jpa)( la valeur d'une clé dupliquée rompt la contr)

Bonjour.
Je ne connais jpa ni eclipselink, mais vous pouvez toujours vérifier que la table de destination sur postgresql n'a pas déjà des enregistrements, ce qui expliquerait l'erreur. Sinon dans la table source le type_sensoriel "profil" a bien pour id 1 ?

Hors ligne

#3 16/05/2012 12:18:43

zero.h
Membre

Re : MySQL--->Postgres (Jpa)( la valeur d'une clé dupliquée rompt la contr)

en fait sur postgres j'ai pas de tables, ils sont crées automatiquement par la couche jpa (Entity) !!
et sur le MySQL les donnees sont pas dupliquéés

Hors ligne

#4 16/05/2012 13:47:12

gleu
Administrateur

Re : MySQL--->Postgres (Jpa)( la valeur d'une clé dupliquée rompt la contr)

Vu l'erreur, j'aurais tendance à penser que le problème du fait que la table existait déjà et que cette ligne faisait déjà partie de cette table. Le mieux est certainement de regarder dans les logs de PostgreSQL pour voir si vous avez des messages d'erreur sur certaines requêtes.

Si, ce que je ferais dans un tel cas, c'est de créer une nouvelle base (pour être sûr de n'avoir rien dedans), de configurer le traçage de toutes les requêtes, et de relancer l'outil de migration.

Tout ça pour dire que, si PostgreSQL vous indique que la valeur est déjà là, c'est qu'elle est bien là. Donc soit elle y était avant que vous lanciez votre programme de migration, soit votre programme de migration migre deux fois la même table.


Guillaume.

Hors ligne

Pied de page des forums