为什么EntityManager插入而不是更新? [英] Why does EntityManager insert instead of updating?

查看:137
本文介绍了为什么EntityManager插入而不是更新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主线程,从数据库中获取对象,然后关闭EntityManager,然后将对象放入队列.辅助线程与该对象进行一些业务往来,然后将其放入完成的队列中.然后主线程从完成的队列中获取对象并合并对象:

I have a main thread where I get an object from database, then close the EntityManager, then put the object into a queue. A worker thread makes some business with the object, then puts it into a finished queue. Then the main thread gets the object from the finished queue and merges the object:

EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
// Print the primary key ID of the object,
// it is NOT empty yes it exists in the db.
em.merge(myObject);
em.getTransaction().commit();
em.close();

我通过在合并之前打印对象来确认对象的主键ID,是的,它存在于数据库中.不幸的是,它引发了来自MySQL的重复键异常.如何? JPA是否不应该知道对象具有ID并更新它,而不是插入它?

I confirm the primary key ID of the object by printing it before merging, and yes it exists in the database. Unfortunately it throws a duplicate key exception from MySQL. How? Shouldn't JPA know that the object has an ID and update it, instead of inserting?

异常中提到的SQL语句是INSERT语句,而不是UPDATE.

The SQL statement that is mentioned in the exception is an INSERT statement, not UPDATE.

实体的主键如下:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "COMPANYID")
private long companyId;

已解决

我正在将对象的列表"字段设置为另一个新创建的对象的列表"字段.然后,由于某种我不了解的原因,EclipseLink认为该对象是一个新对象.上帝知道为什么. JPA的这些东西是非常违反直觉的.您必须是真正的专家才能使用它.否则,它是完全无用的,因为您随时都可能将其弄乱.实际上,它带来的总头痛和时间损失远远超过了它的优势!

SOLVED

I was setting a List field of the object to the List field of another newly created object. Then, for some reason that I don't understand, EclipseLink thinks that the object is a new object. God knows why. This JPA stuff is extremely counter-intuitive. You have to be truly an expert to use it. Otherwise it is totally useless because anytime you can mess it up. In practice the total headache and time loss it creates is much more than its advantages!

无论如何,我通过将另一个对象的元素添加到旧对象来解决该问题,如下所示:

Anyway, I solved the problem by adding the elements of the other object to the old object as follows:

oldObject.getHistories().clear();
for (History history : newObject.getHistories()) {
    history.setCompany(oldObject);
    oldObject.getHistories().add(history);
}

现在EclipseLink可以正确地进行更新,而不是插入新的.如果有人可以解释为什么这种行为,我会很高兴?

Now EclipseLink correctly UPDATES instead of inserting new. I will be happy if someone can explain why this behavior?

推荐答案

之所以发生这种情况,是因为您的EntityManager不了解对象myObject.

This is happening because your EntityManager does not know about the object myObject.

要使代码正常工作,您应该执行以下操作:

For your code to work you should do something like this:

EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Object myObject = em.findById(someId);
em.getTransaction().commit();
object.setName("yourNewName");
.....................
//And now run 
em.getTransaction().begin();
em.merge(myObject);
em.getTransaction().commit();
em.close();

请注意,只有在完成对数据库的所有事务后,我才关闭EntityManager. 而且myObject正是我从em.findById中收到的对象,我不会简单地创建一个新对象,因为那将无法工作.

Please note that I close the EntityManager only after I have done all my transactions needed to the database. And myObject is exactly the one that I recieved from my em.findById, I do not simply create a new object, because that will not work.

这是教程,它可能可以帮助您了解更多.右侧的播放列表,其中包含有关JPA的更多视频).

This is a tutorial that maybe can help you understand a bit more.(you have in the right a playlist with more videos about JPA ).

这篇关于为什么EntityManager插入而不是更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆