In my test app, I'm dealing with objects which didn't arise in a Persistence 
Context, but may need to be 'synchronized' with the corresponding stored data 
record. Can anyone point me to the right strategy for this very simple 
operation? My problem: I don't see a simple signature within the JPA APIs which 
takes account of this situation, and attempts to use promising ones are 
triggering errors.

Ideally I want to be able to say 'write this object's fields into the database, 
using its identity to determine which record to create or update. If it already 
exists then overwrite values, cascading changes to referenced objects as 
overwrites too. I must be missing something about the way these operations 
should be used given the error I'm seeing. 

In the app, filesystem traversals (which generate  filesystem, folder and file 
objects using constructors) are repeated periodically, new items should be 
stored in new records, and existing items should have their records overwritten 
to incorporate any changes in the filesystem (reflected by the objects and 
their fields).

>From looking at the OpenJPA DAO lifecycle, all the EntityManager operations 
>seem to assume your object originated with an EntityManager at some point in 
>the past, even if perhaps it has been detached since. Something which has been 
>independently originated using a constructor, but for which a corresponding 
>identity already exists doesn't seem to be anticipated, at least in the 
>descriptions provided.

The App class in this github folder contains the problem merge(...) call...
https://github.com/cefn/Spring-JPA-MVC-Postgres/tree/709f8be07e91b9b8a1b9dfa4443c2a09d22dc787/src/com/cefn/filesystem

Currently the engine sees duplicate identities as a clash when using merge(), 
rather than an opportunity to synchronise the new object into the corresponding 
data record. I'd expect identity clashes to arise using persist() but not 
merge(). Calling either merge() or persist() on a FileImpl created using a 
constructor in a Filesystem traversal triggers the same error...

org.apache.openjpa.lib.jdbc.ReportingSQLException: ERROR: duplicate key value 
violates unique constraint "file_pkey" {prepstmnt 32879825 INSERT INTO file 
(locationString, location, version, folder) VALUES (?, ?, ?, ?) [params=?, ?, 
?, ?]} [code=0, state=23505]

Of course it's possible for me to hard code a 'does this object already exist 
yet' sort of behaviour, using find(...), then delete, then persist, or 
alternatively comparing all the fields and changing them, but this obviously 
takes away from the advantage of annotation-oriented data objects. Assumptions 
about Data Object identity and fields will end up bleeding out into my 
application code where it should be handled by JPA conventions in the data 
objects.

If I was to manually verify whether an object already exists, I'd want to say 
find(object) not find(identity). Otherwise I have to re-represent all the 
object->identity relationships which JPA has baked in. Once I've retrieved the 
record I'd presumably have to delete it (possibly causing a cascade of 
removes), and reinsert possibly the same data, which just seems wrong, but let 
me know if this is my only option.

Given JPA is supposed to understand what identity and fields my object has, why 
can't I ask it to commit the new data into the database? I'd really benefit 
from suggestions how this should properly be approached.

Cefn
http://cefn.com

Reply via email to