JPA 2.0 Entity update with new relationship fails on persist but succeeds on merge - jpa-2.0

I have the following relationships defined
Entity A has #OneToMany with Entity B that has #OneToOne with Entity C.
At the time of creation for Entity A, I also create Entity B and set the relationship between them. Everything works as expected.
In another transaction,
- Entity A is fetched from the DB, the corresponding Entity B is fetched and then
- Entity C is created.
- Entity C is set on Entity B to forge the relationship between the two.
If i use EntityManager.persist(Entity B), the persistence manager tries and inserts Entity B into the DB again causing a unique constraint violation on the PK of Entity B.
If i user EntityManager.merge(Entity B), everything works as desired.
In this above context of use, why would a persist operation try and create a duplicate since the Entity is managed in this case and it should easily be able to do an update.

JPA requires providers to throw an exception if persist is called on an unmanaged instance. Only merge can be used since it is clear that it takes the data from the instance and merges it into a managed copy. If B were managed, the persist call would be ignored, so it means that some how B gets detached or that it was read in a different entityManager from the one you call persist on.

Related

Adding Entity with Many-To-One association and inverse side already existing in the database

Using Doctrine 2 with Zend Framework 2. Been thinking of how I am meant to persist an entity with a field having a Many-To-One association with another entity that already exists in the database. Would I have to fetch the inverse side from the database first and then adding it to the owning Entity before persisting to the database as in the code below.
//$data = $_POST;
$book = new Book();
$author = $em->getRepository('Application\Entity\Book')->find($data['author_id']);
$book->setTitle($data['title'])
->setISBN($data['title'])
->setAbstract($data['abstract'])
->setYear($data['year'])
->setAuthor($author);
$em->persist($book);
$em->flush();
Normally, without using doctrine, all I have to do is update the author_id field of the Book entity above and persist to the Database. But now I have to make a trip to the Database to fetch the author details to create the entity and thus the association and then persist.
Is this the way it should be done or there is another way that doesnt involve fetching the author's details.
As you can read here
The method EntityManager#getReference($entityName, $identifier) lets
you obtain a reference to an entity for which the identifier is known,
without loading that entity from the database. This is useful, for
example, as a performance enhancement, when you want to establish an
association to an entity for which you have the identifier.
You could simply do this:
$book = new Book();
$book->setAuthor( $em->getReference('Application\Entity\Author',$data['author_id']));

set Doctrine2 entity property without retrieving entire associated object

I have a table Object that has 2 fields that are foreign keys (user_id and teacher_id). After generating the Entities for the X table, the entity only contain the $user and $teacher properties, which forces me to use the associated objects instead of id. So supposing I know the user_id and teacher_id for my object, instead of doing:
$object->setUserId(1)
I have to do:
$user = $this->getDoctrine()->getRepository('MyBundle:Users')->find(2);
$object->setUser($user)
is there no way to work directly with the ids to avoid retrieving the entire object associated to each id?
The framework suggests to use objects when setting the association value. Still – are you sure the record isn't loaded in the memory already? If it is, it will not cause additional SQL statement execution.
If you really need to update the association without loading the object, you can
run native SQL;
try creating Doctrine Proxy object manually and setting it instead.
You can get the proxy object using EntityManager method getReference:
$object->setUser($this->getDoctrine()->getReference('MyBundle:Users', 2));

How to handle EntityNotFoundException in Spring Data JPA (or just standard JPA 2)

I am in the process of cleaning a database. These process involves changing the format of certain fields and getting rid of some data integrity issues.
I developed a program with Spring Data 1.1 to process the records in batches. The problem arises with 2 entities in a #OneToOne relationship. The record for Entity B does not exist although Entity A has a reference to it. My job is to clear the reference to Entity B if that is the case.
The question is: should I pre-process the data to clean this or can I adjust Spring Data or JPA settings to put null in the field if the Entity is not found?
It is "normal" - with this data - to have a FK in Entity A that does not exist in Entity B, so I want to handle this in my code and not have to pre-process the data with an additional step or other tool. The data will be arriving in batches so any pre-processing makes things more complicated for the user.
In summary, I want Spring Data to set the field to null and continue the process instead of getting an org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find....
Perhaps you are looking for the #NotFound annotation?
Here is a post that talks about it.
I have had the same problem because my orm mapping has a wrong #One-to-one unidirectional relationship.

Merging entity with empty related entity in one to many relationship

I have an entity that I have deserialized using JMSSerializer. One of the related items is an ArrayCollection that has no entries in it when the parent object is initially created.
The relationship looks like this
Assembly > has many > HistoryEntries
When I try to merge the deserialized Assembly entity where HistoryEntries is an empty ArrayCollection I get the following error
The given entity of type 'XES\\MpmBundle\\Entity\\History' (unassigned) has no identity/no id values set. It cannot be added to the identity map.
How can I merge and persist an entity where one or more of the relationships has no related entities?

Does it harm anything to include an Entity in a transaction twice?

I am currently programming a tricky update task, where individual Entity objects might be updated more than one time in an atomic transaction. My merge operation looks like this (omitting the try / catch for clarity):
#PersistenceContext protected EntityManager em;
#Resource protected UserTransaction utx;
...
utx.begin();
for (Record r : listOfRecords) em.merge(r);
utx.commit();
If there are multiple references to a given Entity in the list, does anything bad happen?
This is with EclipseLink 2.3.2 as the JPA provider.
Persistent Context : A persistence context is a set of managed entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed by the entity manager.
merge() : Merge the state of the given entity into the current persistence context.
Therefore, there will exist only one instance of an entity at a time in the persistent context. So even if you update your entity multiple times, it will be reflected into database only once, when the transaction commits.