Java 休眠错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已经与会话相关联

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1074081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:11:01  来源:igfitidea点击:

Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

javahibernateorm

提问by harshit

I have two user Objects and while I try to save the object using

我有两个用户对象,当我尝试使用

session.save(userObj);

I am getting the following error:

我收到以下错误:

Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
[com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b]

I am creating the session using

我正在使用创建会话

BaseHibernateDAO dao = new BaseHibernateDAO();          

rtsession = dao.getSession(userData.getRegion(),
                           BaseHibernateDAO.RTREQUESTS_DATABASE_NAME);

rttrans = rtsession.beginTransaction();
rttrans.begin();

rtsession.save(userObj1);
rtsession.save(userObj2);

rtsession.flush();
rttrans.commit();

rtsession.close(); // in finally block

I also tried doing the session.clear()before saving, still no luck.

我也尝试session.clear()过保存之前,仍然没有运气。

This is for the first I am getting the session object when a user request comes, so I am getting why is saying that object is present in session.

这是我第一次在用户请求到来时获取会话对象,所以我明白为什么说会话中存在该对象。

Any suggestions?

有什么建议?

采纳答案by Michael Wiles

I have had this error many times and it can be quite hard to track down...

我多次遇到此错误,并且很难追查...

Basically, what hibernate is saying is that you have two objects which have the same identifier (same primary key) but they are not the same object.

基本上,hibernate 所说的是您有两个具有相同标识符(相同主键)的对象,但它们不是同一个对象。

I would suggest you break down your code, i.e. comment out bits until the error goes away and then put the code back until it comes back and you should find the error.

我建议你分解你的代码,即注释掉一些直到错误消失,然后把代码放回去直到它回来你应该找到错误。

It most often happens via cascading saves where there is a cascade save between object A and B, but object B has already been associated with the session but is not on the same instance of B as the one on A.

它通常通过级联保存发生,其中对象 A 和 B 之间存在级联保存,但对象 B 已经与会话关联,但与 A 上的实例不在 B 的同一实例上。

What primary key generator are you using?

你用的是什么主键生成器?

The reason I ask is this error is related to how you're telling hibernate to ascertain the persistent state of an object (i.e. whether an object is persistent or not). The error could be happening because hibernate is trying to persist an object that is already persistent. In fact, if you use save hibernate will try and persist that object, and maybe there is already an object with that same primary key associated with the session.

我问的原因是这个错误与您如何告诉 hibernate 确定对象的持久状态(即对象是否持久)有关。错误可能发生,因为 hibernate 试图持久化一个已经持久化的对象。事实上,如果您使用 save hibernate 将尝试并持久化该对象,并且可能已经有一个具有与会话关联的相同主键的对象。

Example

例子

Assuming you have a hibernate class object for a table with 10 rows based on a primary key combination (column 1 and column 2). Now, you have removed 5 rows from the table at some point of time. Now, if you try to add the same 10 rows again, while hibernate tries to persist the objects in database, 5 rows which were already removed will be added without errors. Now the remaining 5 rows which are already existing, will throw this exception.

假设您有一个基于主键组合(第 1 列和第 2 列)的 10 行表的休眠类对象。现在,您已经在某个时间点从表中删除了 5 行。现在,如果您尝试再次添加相同的 10 行,而 hibernate 尝试将对象持久保存在数据库中,则将添加已删除的 5 行而不会出错。现在已经存在的剩余 5 行将抛出此异常。

So the easy approach would be checking if you have updated/removed any value in a table which is part of something and later are you trying to insert the same objects again

因此,简单的方法是检查您是否更新/删除了表中的任何值,该值是某事物的一部分,然后您是否尝试再次插入相同的对象

回答by cwap

Are your Id mappings correct? If the database is responsible for creating the Id through an identifier, you need to map your userobject to that ..

您的 ID 映射是否正确?如果数据库负责通过标识符创建 Id,则需要将用户对象映射到该 ..

回答by Michael Wiles

Another thing that worked for me was to make the instance variable Long in place of long

对我有用的另一件事是使实例变量 Long 代替 long


I had my primary key variable long id; changing it to Long id; worked


我有我的主键变量 long id;将其更改为 Long id;工作过

All the best

祝一切顺利

回答by sock_osg

Get the object inside the session, here an example:

获取会话内的对象,这里是一个例子:

MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);

回答by Hein

This is only one point where hibernate makes more problems than it solves. In my case there are many objects with the same identifier 0, because they are new and don't have one. The db generates them. Somewhere I have read that 0 signals Id not set. The intuitive way to persist them is iterating over them and saying hibernate to save the objects. But You can't do that - "Of course You should know that hibernate works this and that way, therefore You have to.." So now I can try to change Ids to Long instead of long and look if it then works. In the end it's easier to do it with a simple mapper by your own, because hibernate is just an additional intransparent burden. Another example: Trying to read parameters from one database and persist them in another forces you to do nearly all work manually. But if you have to do it anyway, using hibernate is just additional work.

这只是 hibernate 产生的问题多于它解决的问题的一点。就我而言,有许多对象具有相同的标识符 0,因为它们是新的并且没有。数据库生成它们。我在某处读到 0 个信号 Id 未设置。持久化它们的直观方法是迭代它们并说休眠来保存对象。但是你不能那样做——“当然,你应该知道 hibernate 以这种方式和那种方式工作,因此你必须......”所以现在我可以尝试将 Ids 更改为 Long 而不是 long 并查看它是否有效。最后,使用您自己的简单映射器更容易做到这一点,因为休眠只是一个额外的不透明负担。另一个例子:尝试从一个数据库读取参数并将它们保存在另一个数据库中,这迫使您几乎手动完成所有工作。

回答by caarlos0

You always can do a session flush. Flush will synchronize the state of all your objects in session (please, someone correct me if i'm wrong), and maybe it would solve your problem in some cases.

您始终可以执行会话刷新。Flush 将同步会话中所有对象的状态(如果我错了,请有人纠正我),并且在某些情况下它可能会解决您的问题。

Implementing your own equals and hashcode may help you too.

实现您自己的 equals 和 hashcode 也可能对您有所帮助。

回答by Frithjof

I also ran into this problem and had a hard time to find the error.

我也遇到了这个问题,很难找到错误。

The problem I had was the following:

我遇到的问题如下:

The object has been read by a Dao with a different hibernate session.

该对象已被具有不同休眠会话的 Dao 读取。

To avoid this exception, simply re-read the object with the dao that is going to save/update this object later on.

为避免此异常,只需使用稍后将保存/更新此对象的 dao 重新读取该对象。

so:

所以:

class A{      

 readFoo(){
       someDaoA.read(myBadAssObject); //Different Session than in class B
    }

}

class B{



 saveFoo(){
       someDaoB.read(myBadAssObjectAgain); //Different Session than in class A
       [...]
       myBadAssObjectAgain.fooValue = 'bar';
       persist();
    }

}

Hope that save some people a lot of time!

希望能节省一些人很多时间!

回答by Thupten

Check if you forgot to put @GenerateValue for @Id column. I had same problem with many to many relationship between Movie and Genre. The program threw Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session error. I found out later that I just have to make sure you have @GenerateValue to the GenreId get method.

检查您是否忘记为 @Id 列放置 @GenerateValue。我对电影和流派之间的多对多关系有同样的问题。程序抛出休眠错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已经与会话错误相关联。后来我发现我只需要确保你有 @GenerateValue 到 GenreId get 方法。

回答by user1609848

You can check your Cascade Settings. The Cascade settings on your models could be causing this. I removed Cascade Settings (Essentially not allowing Cascade Inserts/Updates) and this solved my problem

您可以检查您的级联设置。模型上的级联设置可能会导致这种情况。我删除了级联设置(基本上不允许级联插入/更新),这解决了我的问题

回答by Rahul N

USe session.evict(object);The function of evict()method is used to remove instance from the session cache. So for first time saving the object ,save object by calling session.save(object)method before evicting the object from the cache. In the same way update object by calling session.saveOrUpdate(object)or session.update(object)before calling evict().

使用methodsession.evict(object);函数evict()用于从会话缓存中移除实例。所以第一次保存对象时,session.save(object)在从缓存中驱逐对象之前通过调用方法保存对象。以同样的方式通过调用session.saveOrUpdate(object)session.update(object)在调用 evict() 之前更新对象。