merge in doctrine 2 not working giving error - doctrine-orm

I am trying to update a row in a table. I am using doctrine 2 ORM. I am trying to update a row using merge(), which is said can be used to update a row. But it gives a error saying
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
I am new to doctrine 2. please suggest what can i do?

When to merge
First off: You only need $em->merge() when you have an entity that isn't managed by the EntityManager, but you want it to be. A common use-case is when you have a serialized entity, and want the EntityManager to start managing it.
So merging entities is not directly related to updating entities in the database.
If you simply find (using $repo->find*()) an entity and make changes, calling $em-flush() is sufficient. The entity is already managed by the EntityManager and there's no need to merge it.
How to merge
A common mistake when using $em->merge() is that the passed entity itself becomes managed. This isn't true, $em->merge() returns a new object that represents the managed entity.
$managedEntity = $em->merge($detachedEntity);
After this line of code, $detachedEntity is still detached (meaning it still isn't managed by the EntityManager). It's $managedEntity which you can start using to make changes.
Your code
Given the code you've put in the comments, you probably want to do something like this:
$user = $entityManager->getRepository('User')->find($_REQUEST['id']);
$user->setName($_REQUEST['name']);
$user->setPassword($_REQUEST['pass']);
$entityManager->flush();
PS: It looks like you're saving the the plain-text password in the database. That's never a good idea.

Related

Doctrine ORM "Multiple non-persisted new entities were found through the given association graph:"

$added_obj = [];
foreach ($something as $data) {
$obj = $this->class->function($data, $par2);
if (null !== $obj && !(array_key_exists
(->getVal1(), $added_obj[$obj->getVal1()] === $$obj->getVal2())) {
$this->persister->persist($obj);
$added_bank_account[$obj->getVal1()] = $obj->getVal2();
} else {
}
}
What the code does: It calls an function which returns an entity or null. If an entity was created there is an check if 2 values already exists in an array, if not, than persist and add the 2 values to an array as key/val pair.
But, when an entity is created and it already exists in the array i don't want it to be persisted, but I want to do nothing with it.
But, when I do absolutely zero with it I got the error:
```Multiple non-persisted new entities were found through the given association graph:
A new entity was found through the relationship 'MyCompany\Client\Entity\Client#something' that was not configured to cascade persist operations for entity:
which makes sense because doctrine doesn't know what to do with the created entity. How can I "destroy" the created entity so that the problem is solved.
When there is only 1 object created everything works fine.
In your case you can simply merge or clear the entity from EntityManager
ex :
$em->merge($obj);
OR
$em->clear($obj);
I was facing the same issue because it was trying to insert a duplicated registry in a particular table, when in fact I was just trying to update it.
I was doing a persist with a flush right after.
So I found that (obvious for many, but certainly helpful):
->merge
will duplicate the registry in many cases, if the id is not set properly.
If you are trying to update an entity, this is not a good idea.
->persist
In the same way, if you are trying to update an entity, you may not use it. It's used to add a new entity to the db. To update a record, you may just use flush as you can see in this example from the docs.
I had the same problem and googling this error did not give me much results, but it appeared that in case of only one entity (not multiple) doctrine gives different error message, which has a solution that worked for multiple entities too. So, let me leave here a link for it: Doctrine - A new entity was found through the relationship
This problem occurs if you got the related entity in another object manager. For example, if there was previously a check for duplication through an exception and resetting the manager.

Doctrine ORM how to save an UPDATE of my object to the database (equivalent of SQL UPDATE query)

I'm new to Doctrine and I can't seem to find an answer to this.
To save a newly created object to the database (equivalent of SQL INSERT query), I'm using
$this->getEntityManager()->persist($category);
$this->getEntityManager()->flush($category);
And to delete one (equivalent of SQL DELETE query), I'm using
$this->getEntityManager()->remove($category);
$this->getEntityManager()->flush($category);
Now, how do I save updates to my $category object to the database? I'm looking for the Doctrine equivalent of an UPDATE query.
Surely Doctrine ORM must have a simple method to do this, without having to use DQL?
Well there is no need for specific update query.
With doctrine you can update objects like this. Let's suppose you have category object with field name. So we will try to update it.
$newName = 'hello world';
$category->setName($newName);
$this->em->flush(); // without passing the object
This will update you entity.
So following up from this, we have learnt, that you can update entities, by just using setters and setting new values, and after that you flush. It will handle things automatically.

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.

Selecting a single record with Doctrine2

I am trying to retrieve a single row from a table. This row contains filed that hold foreign keys into another table, which in turns is related to yet another table. I am trying to get just one row returned, yet, the problem is, it returns not only the row but ALL the objects that are jointly related to that table as well. As I have to deal with a fairly large amount of data, the returned object is very cumbersome as it contains all the related data as well. In some cases my script simply times out because there is just far too much data to grab.
My question is; is there a way to retrieve just a single record without the associated fluff with it? I am basically accessing the table via the entityManager from the repository, then trying to get my record by using the ->find($id) method.
I am sure this is something stupidly simple but I can't seem to figure this out. Thanks in advance for any help, it is much appreciated.
Doctrine 2 use "lazy loading", it means that the associated objects are not really retrieved from the database while you don't try to access them.
So the find($id) is just fine.

JPA generating an invalid column

Helo there.
I am attempting to a execute a many-to-many get all query. To be clear, I am attepmting to get a collection within a collection to be pulled back. Ie, we will get a result set, but in that result set, there will be a collection of all objects linked to it via a foreign key. Now, to do this, I have a collection which I annotate thusly...
#ManyToMany
#JoinTable(name="QUICK_LAUNCH_DISTLIST",
joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"),
inverseJoinColumns=#JoinColumn(name="LIST_ID"))
private Collection<QuickLaunchDistlist> distributionLists;
Which seems to be just about text book...
I call a named query which looks like this...
#NamedQuery(name="getQuickLaunch", query = "SELECT q FROM QuickLaunch q")
Which is executed like so...
qlList = emf.createNamedQuery("getQuickLaunch").getResultList();
Every time I make this call, I get back the expected data in the first collection. But none of the collections seem to populate with it. To find out why, I looked at the sql being generated by the call... This is what I find...
I get this exception...
This is a FFDC log generated for the Default Resource Adapter from source:com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeQuery
The exception caught:java.sql.SQLSyntaxErrorException: ORA-00904: "T1"."QL_DISTLIST_ID": invalid identifier
SQL Error Code is 904 SQL State is :42000
Along with this query...
SELECT t1.QL_DISTLIST_ID, t2.LIST_ID, t2.CREATE_DATE, t2.CREATE_USERID, t2.description, t2.flag, t2.MOD_DATE, t2.MOD_USERID, t2.ORGANIZATION_ID, t2.owner, t2.STATUS_ID, t1.MESSAGE_TYPE_ID, t1.MOD_DATE, t1.MOD_USERID, t1.QUICK_LAUNCH_ID FROM EPCD13.QUICK_LAUNCH_DISTLIST t0, EPCD13.QUICK_LAUNCH_DISTLIST t1, EPCD13.DISTRIBUTION_LIST t2 WHERE t0.QUICK_LAUNCH_ID = ? AND t0.LIST_ID = t1.QL_DISTLIST_ID AND t1.LIST_ID = t2.LIST_ID(+)
If you look at the first column it request's to pull back you will notice that it selects t1.QL_DISTLIST_ID... Problem is, I have no such named column any where in my db!?!?!? Why on earth is that column being called? How does JPA generate the queries that it calls? If I knew that, I might be a little closer to figuring out what went wrong here or what I did wrong. Any help would be greatly appreciated.