JPA Seriendruck-Ergebnisse in doppelter Eintrag von ausländischen Unternehmen
FRAGEN:
Weiß jemand, wie man Zusammenführen, ohne EntityManager
versuchen Sie zu re-legen Sie die ausländische Person?
SZENARIO:
Nur um ein Szenario, das am ehesten mein Fall: ich habe zwei Entitäten
@Entity
@Table(name = "login", catalog = "friends", uniqueConstraints =
@UniqueConstraint(columnNames = "username"))
public class Login implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "username", unique = true, nullable = false, length = 50)
private String username;
@Column(name = "password", nullable = false, length = 250)
private String password;
}
@Entity
@Table(name = "friendshiptype", catalog = "friends")
public class FriendshipType implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "username")
private Login login;
@Column(name = "type", unique = true, length = 32)
private String type;
...//other fields go here
}
Sowohl die Login
Unternehmen und die FriendshipType
Entität gespeichert werden, um die Datenbank getrennt. Dann, später, ich brauche, um Seriendruck eine Login
Zeile mit einem FriendshipType
Zeile. Wenn ich Anrufe entityManager.merge(friendship)
es versucht, legen Sie einen neuen Login
was natürlich die Ergebnisse in der folgenden Fehlermeldung
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'myUserName1350319637687' for key 'username'
Error Code: 1062
Call: INSERT INTO friends.login (password, username) VALUES (?, ?)
Meine Frage, ist: wie führe ich zwei Objekte ohne enityManager versucht, wieder das fremde Objekt?
- Dies hat wohl nichts zu tun mit dem Problem, aber sollte es nicht sein, @JoinColumn(name = "id"). Alle Beispiele, die ich gesehen habe, join über die id-Eigenschaft.
- Simone ich versuchen deinen Vorschlag, aber keine Veränderung.
- OK - danke für das lassen mich wissen. Hoffe du bekommst bessere Antworten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist, wie ich das problem lösen. Ich schließlich die Figur der Grund der Zusammenführung nicht auflösen wird, weil der login.id wird automatisch generiert, durch das JPA. Also da ich wirklich nicht benötigen eine automatisch generierte id-Feld, Entferne ich es aus dem schema und verwenden
username
als@id
Feld:Andere Lösung, die mir einfiel, die ich nicht umsetzen kann aber jemand anderes helfen, sollten Sie brauchen, um einen automatisch generierten id-Feld.
Stattdessen erstellen Sie eine Instanz der
Login
für die Fusion, erhalten Sie die Instanz aus der Datenbank. Was ich meine ist, stattTun, eher
So, ein neues id-Feld wird nicht generiert, wodurch die Einheit scheinbar anders.
Dank und up-votes an alle für die Hilfe, besonders an @mijer for being so geduldig.
@ManyToOne
Beziehung sinken Sie in Ihrem Kopf (die impedance-mismatch-Probleme sind häufiger als Sie denken, und fallenlassen der PK kann die Lösung nicht sein die nächste Zeit, die Sie auf einer von denen).username
als Primärschlüssel. Wie ich schon erwähnt, in der alternativen Lösung konnte ich sehr gut halten das auto-generierte Feld, wenn ich es brauchte. Ich dachte@ManyToOne
könnte irreführend sein, da die realationship ist wirklich@OneToOne
. Immer noch, entweder man hat das problem nicht lösen, und ich bin immer noch mit@ManyToOne
in meine Lösung-ich habe nicht geändert, es noch zurück.@ManyToOne
Anmerkung sollte das problem lösen, es sei denn, Sie beharren nicht neueLogin
Objekte mit IhrenFriendshipType
(was Ihr zweiter Vorschlag wäre zu lösen).Können Sie machen Sie Ihre
@JoinColumn
nicht aktualisierbar:Oder versuchen, zu aktualisieren /abrufen
Login
Person wieder vor dem Zusammenführen derFriendshipType
:Aber, wie von anderen vorgeschlagen, ich denke, dass
FriendshipType
besser wäre, vertreten durch eine@ManyToOne
Beziehung oder vielleicht durch eine Einbettbare oder ElementCollectionUpdate
Noch eine andere option ist die änderung der Besitz-Seite:
Dies wird Auswirkungen auf Ihre Daten-Modell (login-Tabelle wird ein
friendshiptype_id
Spalte, anstatt die andere Weise herum), aber es wird verhindern, dass die Fehler, die Sie bekommen, da Beziehungen stets erhalten bleiben, indem die besitzende Seite.Haben Sie versucht
cascade=MERGE
? I. e.UPDATE
Eine andere Möglichkeit ist die Verwendung
@ManyToOne
(es "speichern unter" der Verein ist einzigartig)@JoinColumn(name = "login_id")
, die sich in der Datenbank-schema alsCONSTRAINT FK_friendshiptype_login_id FOREIGN KEY (login_id) REFERENCES login (id)
. Aber ich bekomme immer noch den Fehler.@ManyToOne
statt@OneToOne
?cascade={CascadeType.MERGE,CascadeType.PERSIST}
" - der ganze Satz macht. Keine änderung.Können Sie es mit Ihrem original @Id-setup. also
Können Sie, aber Sie brauchen nicht zu ändern:
Der trick ist, müssen Sie starten durch laden aus der DB, über em.finden(...) oder em.createQuery(...). Dann die id ist garantiert aufgefüllt werden mit dem richtigen Wert aus der DB.
Dann können Sie trennen Sie die Einheit durch die Beendigung einer Transaktion (für ein transaction-scoped entity-manager in einer session-bean), oder durch den Aufruf von em.trennen Sie(ent) oder em.clear(), oder durch serialising der Person und übergeben es über das Netzwerk.
Dann können Sie aktualisieren Sie die Einheit, die ganze Zeit, halten Sie die original-id-Wert.
Dann können Sie call-em.merge(ent) und Sie haben noch immer die richtige id. Ich glaube jedoch, muss das Unternehmen bereits vor-vorhanden in der persistenten Kontext des entity-manager in diesem Augenblick, sonst wird Sie denken, dass Sie eine neue Entität (mit manuell gefüllt-id), und versuchen Sie, LEGEN Sie in Transaktion flush/commit.
Also der zweite trick ist, um sicherzustellen, dass die Entität geladen, an der Stelle der Zusammenführung (über em.finden(...) oder em.query(...) wieder, wenn Sie haben ein neues persistentes Kontext-und nicht dem original).
🙂