2016-09-23 6 views
0

ich bin in diesem Augenblick in einem Projekt arbeiten, ist hier ein Stück Code:Wie erstellt man neue Zeilen ohne JPA als Update?

public boolean getAll() { 
     TypedQuery<Tag> query = em.createQuery("SELECT c FROM Tag c WHERE (c.tagName !=?1 AND c.tagName !=?2 AND c.tagName !=?3) ", Tag.class); 
     query.setParameter(1, "Complete"); 
     query.setParameter(2, "GroupA"); 
     query.setParameter(3, "GroupB"); 

     List<Tag> Tag= query.getResultList(); 

Aber wenn ich versuche, so etwas zu tun:

Tag.get(2).setTagName = "Hello"; 
em.persist(Tag.get(2)); 

Er hält es für ein Update sein anstelle von einem erstellen? Wie kann ich JPA verständlich machen, dass es nicht datenbankbezogen ist, um die Ketten mit der Datenbank zu trennen und ein neues Register zu erstellen, wobei nur der Name geändert wird?

Vielen Dank für jede Hilfe! Mit freundlichen Grüßen!

EDIT:

Mit der em.detach kurz bevor es Werte und persistierende jeder der Liste zu ändern funktionierte gut!

Danke allen!

Antwort

1

Die Entscheidung, ob ein neues Entitätsobjekt aktualisiert oder erstellt werden soll, basiert auf dem Primärschlüssel. Sie verwenden wahrscheinlich eine ID für jedes Objekt. Ändern oder entfernen Sie es und bleiben Sie dann bestehen. Dies sollte einen neuen Eintrag erstellen.

Wenn das nicht funktioniert, könnte man das Objekt aus dem Entity Manager zuerst lösen müssen:

em.detach(tagObj); 

und bleiben es danach:

em.persist(tagObj); 

Sie stattdessen auch eine Aktualisierung erzwingen kann der Erstellung mit

em.merge(tagObj) 

Es gibt keine Entsprechung für erzwungene Erstellung AFAIK. persist wird beides abhängig von PK tun.

+0

Vielen Dank Hubert, das hat gut funktioniert! –

1

Sie haben uns gezeigt, wie Sie Ihre Liste sind zu erhalten, aber es gibt zwei wichtige Punkte hier:

  1. alles aus einer EntityManager lesen verwaltet wird - JPA prüft diese verwalteten Objekte für Änderungen und wird sie bei Bedarf mit der Datenbank synchronisieren (entweder durch Festschreibung der Transaktion oder Aufruf flush).

  2. auf einer verwalteten Einheit aufrufen bestehen ist eine no-op - das Unternehmen ist bereits gelungen, und wird mit der Datenbank synchronisiert werden, wenn es ist noch nicht drin.

Also die erste Tag.get (2) .setTagName = "Hallo"; Call ist, was Ihre Aktualisierung verursacht, während die Persistenz eine No-Op ist.

Sie müssen stattdessen eine neue Instanz Ihres Tag-Objekts erstellen und das Feld festlegen. Erstellen Sie eine Klonmethode für Ihr Objekt, die alles außer dem ID-Feld kopiert, und rufen Sie dann das Ergebnis auf, um eine Einfügung für eine neue Entität zu erhalten.

+0

Ich tat dies, aber als ich es einstellte, erzeugte es den gleichen Fehler, nur mit em.In diesem Fall vorher loslassen, da meine ID in meinem Fall geändert werden muss. Es tut mir leid, wenn ich nicht klar darüber war. –

+0

Ich bin mir nicht sicher, was du gesagt hast, dass du es getan hast, das den gleichen Fehler verursacht hat. Sie können den gleichen Fehler nur bekommen, wenn Sie eine Entität beibehalten, die den gleichen Primärschlüssel wie eine existierende Entität hat - ich habe gesagt, dass Sie alles, was Sie außer der ID brauchen, klonen müssen. Lassen Sie das Feld leer, damit der Anbieter ihm einen neuen Namen zuweist, oder legen Sie einen Wert fest, der nicht verwendet wird. Trennen entfernt die Entität aus dem Kontext, funktioniert jedoch möglicherweise nicht wie erwartet, wenn Sie versuchen, die ID zu ändern und sie dem Persistenzkontext erneut zuzuordnen, insbesondere wenn Sie andere Entitäten haben, die auf sie verweisen. – Chris

+0

Also, was ich getan habe, war ein neues Objekt zu erstellen, wie: new Tag, dann habe ich vielleicht einen Fehler gemacht, um das zu tun wie zum Beispiel Tag_ = Tag.get (1). Aber ich habe auch versucht, jeden Wert wie dieses Tag_.setAttribute (Tag.get (1) .getAttribute()) zu kopieren. Und vor em.detach() hat es nicht wie erwartet funktioniert. Aber offensichtlich könnte es mein Fehler in irgendetwas in meinem Code sein. –

Verwandte Themen