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 entityManager is null in Pointcut
JPA: NamedQuery of name: <query> not found
Glassfish EJB 3 OpenJPA 2
owned and unowned relationships
Is there a way to get all managed entities from an EntityManager
Multi-Tenant Seam + JPA Application
JPA mapping error for sequence number
JPA : What is the behaviour of merge with lazy initialized collection?
JPA problem one-to-one association cascade= PERSIST
JPQL we can't CONCAT(String, Integer) EclipseLink?
Cant persist an entity
How to implement self join in JPA?
Unneeded column added trying to set up OneToMany relationship
EntityManager doesn't refresh the data after querying
How To modify Eclipselink JPA 2.0 connection retry behavior
How to have 2 collections of the same type in JPA? (EclipseLink)

Categories

HOME
url-redirection
twitter-bootstrap-3
deep-learning
fuelux
gdb
string
c99
forms
zend-framework
graphics
gradient
carousel
gembox-spreadsheet
bookmarks
teechart
okhttp
openstreetmap
mod-security
rtf
filechannel
internationalization
soci
nim
delphi-xe5
charles
strongname
expressionengine3
linked-data
handler
custom-controls
weather
catch-unit-test
papaparse
swagger-php
xdocreport
bc
signals-slots
visa
sharp-snmp
drupal-theming
importerror
signal-strength
memory-mapping
proget
robomongo
vugen
convex-optimization
trojan
corruption
page-replacement
custom-font
opengl-4
swingworker
reachability
redistributable
burrows-wheeler-transform
greatest-n-per-group
model-associations
wso2developerstudio
cda
redis-cluster
fuzzywuzzy
realsense
spring-retry
rewrite
morton-number
slash
viola-jones
ocra
nutiteq
telepat
ms-access-2000
xmltype
cross-join
apache-spark-1.3
webmatrix-3
boost-program-options
crowd
linkedin-jsapi
jjaql
gnumeric
extjs2
drupal-nodes
jammer
kendo-dataviz
cnf
cmmi
dolby-audio-api
traceability
robotlegs
fragmenttransaction
sentestingkit
boost-msm
infobright
android-holo-everywhere
lr
inline-formset
object-database
zen
dsl-tools
todos
appliance

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App