Frage

Ich bin mit JPA mit Hibernate unter, und ich habe Mühe, den Weg zur Arbeit verschmelzen, aber bevor ich die Probleme beschreibe ich mit JPA bin begegnen, lassen Sie mich legen, was ich zu tun versuche, für alle Fälle meine Probleme Stiele von meinem Ansatz.

Ich habe Daten aus auf System, das ich brauche, in ein anderes System zu platzieren. Um dies zu tun ich die Daten lese dann neue ORM-Objekte konstruieren auf der Grundlage dieser Daten, ich will dann bestehen bleiben die ORM der Datenbank-Objekte in. Nun, wenn die Datenbank leer ist, funktioniert das Programm ohne Probleme mit einem einfachen em.persist (Objekt) Aufruf. Jedoch habe ich diesen Prozess ausführen zu können, wollen, wenn die Datenbank Daten enthält, neue Daten hinzufügen und alte Daten bei Bedarf zu aktualisieren, das ist, wo ich Probleme habe.

Ich habe eine einfache Prüfung, um zu sehen, wenn der Artikel bereits in der Datenbank vorhanden ist, wenn nichts gefunden wird, ich bestehen bleiben, wenn der Datensatz vorhanden ist, versuche ich, eine Zusammenführung. Welche schlägt mit einem doppelten Datensatz Fehler;

ERROR JDBCExceptionReporter - Violation of UNIQUE KEY constraint 'UK-SubStuff-StuffId-SubStuffNumber'. Cannot insert duplicate key in object 'SubStuff'.

Es kommt mir seltsam, dass die em.merge () eine Einlage anstelle einer Aktualisierung versucht (ich dies durch SQL-Protokollierung bestätigt).

Hibernate: insert into SubStuff (SubStuffNumber, StuffId, Name, TypeId) values (?, ?, ?, ?)

sollte ich anmerken, dass ich Objekte verwende, die Kaskade in Unterobjekte. Der Fehler wird auf einem Unterobjekt auftreten, das macht Sinn für mich, wie ich es erwarten würde zuerst die Unterobjekte zu versuchen und fusionieren.

Unten ist mein Code, bitte auf den Rohzustand entschuldigen, ich habe ein paar Abhilfe zu dokumentieren versucht, nähert sich hier.

private void storeData(Collection<Stuff> Stuffs) {

    for (Stuff stuff : Stuffs) {
        //I think this first block can be safely ignored, as I am having no issues with it
        //  Left it in just in case someone more experianced then I sees the root of the issue here.
        Collection<SubStuff> subStuffs = stuff.getSubStuffCollection();
        for (SubStuff s : subStuffs) {
            //Persist SubStuff Type, which DOES NOT cascade,
            //  due to it not having an internal SubStuff collection
            Query q = em.createNamedQuery("SubStuffType.findByType");
            q.setParameter("type", f.getTypeId().getType());
            try {
                SubStuffType sst = (SubStuffType) q.getSingleResult();
                s.setTypeId(sst);
            } catch (NoResultException ex) {
                if (logger.isDebugEnabled()) logger.debug("SubStuff Type not found, persisting");
                em.persist(s.getTypeId());
            }
        }

        if (em.find(Stuff.class, stuff.getId()) == null) {
            //Persist on Stuffs will cascade to SubStuffs
            em.persist(stuff);
        } else {
            //  Failing to merge SubStuff, tries to insert duplicate
            //  Merge SubStuff first
            // The block below is my attempt to merge the SubStuff Collection before merging Stuff,
            //  it creates the same isuse as a straight merge of Stuff.
            Collection<SubStuff> mergedSubStuffs = new ArrayList<SubStuff>(SubStuffs.size());
            for (SubStuff s : SubStuffs) {
                Query q = em.createNamedQuery("SubStuff.findBySubStuffNumberStuffId");
                q.setParameter("SubStuffNumber", s.getSubStuffNumber());
                q.setParameter("StuffId", stuff.getId());
                try {
                    SubStuff subStuff = (SubStuff) q.getSingleResult();
        // -----> Merge fails, with an duplicate insert error
                    SubStuff mergedSubStuff = em.merge(s);
                    mergedSubStuffs.add(mergedSubStuff);
                } catch (NoResultException ex) {
                    throw ex;
                }
            }
            stuff.setSubStuffCollection(mergedSubStuffs);

        // -----> This will fails with same error as above, if I remove the attempt
            //  to merge the sub objects
            em.merge(stuff);
        }
    }
}

Wenn jemand mit JPA Erfahrung kann mir helfen würde ich wirklich zu schätzen. Die differances zwischen Hibernate saveOrUpdate () und PPV-merge () sind Auslösung mich offensichtlich, aber trotz mehrerer Artikel lesen auf EnityManger der merge, kann ich noch nicht wickeln meinen Kopf herum, was hier vor sich geht.

Vielen Dank für Ihre Zeit.

War es hilfreich?

Lösung

Der Fluch der Stackoverflow hat wieder zugeschlagen. Nach der Arbeit mich auf diesem Problem für etwa einen Tag entscheiden, diese Frage zu stellen, innerhalb von 20 Minuten, die ich ein Aha-Erlebnis hatte und löste es. Teilweise, weil ich hatte meine Gedanken genug geklärt, die Frage zu stellen. Beim Nachdenken darüber, welche Informationen könnte auf die Frage relevant sein, die ich merkte, dass mein Auto erzeugten Schlüssel schuld waren (oder meine richtig, mein dummen Nicht-Umgang mit ihnen auf einer Zusammenführung).

Mein Problem ist, dass SubStuff (worst Ersatz Benennungsschema, tut mir leid, dass) eine automatisch generierte künstlichen Primärschlüssel hat. Also beim Einarbeiten ich tun musste;

SubStuff subStuff = (SubStuff) q.getSingleResult();
//++++++++
s.setId(subStuff.getId());
//++++++++

//The following code can be removed.
//--- SubStuff mergedSubStuff = em.merge(f);
//--- mergedSubStuffs.add(mergedSubStuff);

Damit wird der Primärschlüssel zu der Zeile, die in der Datenbank bereits vorhanden ist und bei ersten Tests scheint gut zu funktionieren.

Der Aufruf fusionieren kann auf nur den Aufruf vereinfacht werden, um em.merge (Material), wie das die substuff Objekte kaskadiert werden und die mergedsubstuff Sammlung kann alle zusammen entfernt werden, da wir nicht mehr eine Zusammenführung innerhalb dieser Schleife zu tun.

Danke an alle, die durch meine lächerlich lange Frage zu lesen, hoffentlich wird meine Frage an jemanden in der Zukunft nützlich sein.

Andere Tipps

Ihr Problem ist mit den folgenden zwei Zeilen:

Collection<SubStuff> mergedSubStuffs = new ArrayList<SubStuff>(SubStuffs.size());
...
stuff.setSubStuffCollection(mergedSubStuffs);

JPA wird neue Kollektion als komplett neue Reihe von Untereinheiten betrachtet und wird immer als solche ein. Halten Sie die Arbeit mit Original-Sammlung von SubStuff innerhalb Stuff Unternehmen, und Sie werden in Ordnung sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top