jpa


Why does JPA do a double insert upon merge()


In EclipseLink, I run into a problem where an element is inserted twice, resulting into a primary key violation. The scenario is as follows:
I have three entities, Element, Restriction and RestrictionElement. The entity RestrictionElement acts as a many-to-many relationship between the two others.
When I create a new RestrictionElement and merge the Element, the RestrictionElement is inserted twice. The code:
// element is an Element, restriction is a Restriction. Both are already in present in the database.
RestrictionElement newRestrictionElement = new RestrictionElement(restriction, element);
Transaction transaction = new Transaction();
em.merge(element); //em is the EntityManager
transaction.commit();
However, if I remove the line restriction.getReferencedRestrictionElements().add(this); the RestrictionElement is inserted once.
Can anyone explain why this happens? Or point to a document that explains how to work out what the merge() command does?
Relevant JPA code: (I'll only given a small part. There aren't any other big problems with the code.)
public class RestrictionElement {
#JoinColumns({#JoinColumn(name = "ELEMENT_ID", referencedColumnName = "ID"),#JoinColumn(name = "ELEMENT_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Element element;
#JoinColumns({#JoinColumn(name = "RESTRICTION_ID", referencedColumnName = "ID"),#JoinColumn(name = "RESTRICTION_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Restriction restriction;
public RestrictionElement(Restriction restriction, Element element) {
this.restriction = restriction;
this.element = element;
restriction.getReferencedRestrictionElements().add(this);
element.getReferingRestrictionElements().add(this);
}
}
public class Element {
#OneToMany(mappedBy = "element")
private List<RestrictionElement> referingRestrictionElements = new ArrayList<RestrictionElement>();
}
public class Restriction extends Element {
#OneToMany(mappedBy = "restriction", cascade = { ALL, PERSIST, MERGE, REMOVE, REFRESH })
private List<RestrictionElement> referencedRestrictionElements = new ArrayList<RestrictionElement>();
}
How do your persist RestrictionElement? My guess is when you persist it you get one copy, then a second when you merge the Element with the reference to it.
Try using persist() for new objects, and related the objects after they are managed with the correct managed copy.
I got a similar issue when I run my program, but the issue is not there under step by step debugging.
I resolved the issue by changing List to Set in the OneToMany relationship.
Don't forget that once you retrieve an instance of the class using JPA, the instance becomes managed, any changes to it will be automatically merged into the database.
By default, this merge will occur at the moment you query the table. Therefore the following situation can happen:
query (find by ID)
update (setName = "xx")
query another class that has a direct relationship to this one (find by ID again)
in a situation similar to the above, the second find will effectively issue a merge to the first table. (I'm not sure exactly of the details or scenarios here).
My suggestion is that you issue every single query (findById for example) or every instance you have before you start modifying it (ie, set, etc).
Hope it helps.

Related Links

JPA: Unidirectional ManyToMany with existing object to be inserted
spring data lazy loading
JPA Entity with id from referencing class
JPA: implicity persist #ManyToOne entities
modifying the persistence.xml at runtime
Insert object with composite primary key
In JPA, having a many-to-one as primary key throws referential integrity constraint violation
JPA never fetcheable #OneToMany
JPA reading/referencing annotations programatically
JPQL “DISTINCT” returns only one result
Fuse ESB JPA Entity not persisting
Spring Data findBy Enum
PersistenceUnitInfo implementation in EclipseLink
Does Guice Persist provide transaction scoped or application managed EntityManager?
One to Many relationship in JPA
How to optionally persist secondary table in Eclipselink

Categories

HOME
ng-idle
ecmascript-6
google-spreadsheet
mjml
vxml
tvos
iis-6
missing-data
retrofit2
opengl-3
okhttp
activecollab
filechannel
alpacajs
google-data-studio
html5-appcache
soci
nim
selinux
google-maps-autocomplete
event-store
stackexchange
asymptotic-complexity
gp
sqsh
glib
catch-unit-test
installshield-le
python-import
lubridate
fiware-cygnus
roblox
apiary.io
parse-tree
cd
ideascript
modernizr
bc
demo
cin
skylink
android-ibeacon
dotnet-httpclient
tf
lightning
remedy
custom-font
video-conferencing
reporting-services-2012
latin
mta
x-tag
android-wake-lock
fuzzywuzzy
boomerang
java-money
finalbuilder
graphics2d
zend-currency
rrule
mmwormhole
formview
functional-java
ios8-extension
dot42
dsym
gae-quotas
sbcl
light
frameworkelementfactory
patricia-trie
rmiregistry
boost-signals
lambdaj
koken
agility.js
entity-attribute-value
pylucene
rmdir
multiplatform
ie-compatibility-mode
office-2007
aspmenu
qtabbar
cfwindow
build-environment
dsl-tools
online-storage
mathematical-typesetting
cardspace
idatareader

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App