首页 / HIBERNATE / hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法
hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含14537字,纯文字阅读大概需要21分钟。
内容图文
先将自己出现错误的全部代码都贴出来:
hibernate.cfg.xml
<? xml version="1.0" encoding="UTF-8" ?> <! DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" > < hibernate-configuration > < session-factory > < property name ="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property><property name="hibernate.connection.password">tiger</property><property name="hibernate.connection.url">jdbc:mysql:///hibernate?useUnicode=true&characterEncoding=UTF-8</property><property name="hibernate.connection.username">root</property><property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><property name="show_sql">true</property><property name="format_sql">true</property><property name="hbm2ddl.auto">create</property><mapping resource="com/third/Dao1/Grader1.hbm.xml"/><mapping resource="com/third/Dao1/Students1.hbm.xml"/></session-factory></hibernate-configuration>
Students1.java
package com.third.Dao1; import java.io.Serializable; public class Students1 implements Serializable { privateint sid; private String sname; private String sgender; public Students1() { } publicint getSid() { return sid; } publicvoid setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } publicvoid setSname(String sname) { this.sname = sname; } public String getSgender() { return sgender; } publicvoid setSgender(String sgender) { this.sgender = sgender; } }
Grader1.java
package com.third.Dao1; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Grader1 implements Serializable { privateint gid; private String gname; private Set<Students1> stuSet=new HashSet<Students1>(); public Grader1() { } publicint getGid() { return gid; } publicvoid setGid(int gid) { this.gid = gid; } public String getGname() { return gname; } publicvoid setGname(String gname) { this.gname = gname; } public Set<Students1> getStuSet() { return stuSet; } publicvoid setStuSet(Set<Students1> stuSet) { this.stuSet = stuSet; } }
由eclipse帮助生成的hbm.xml文件:
Students1.hbm.xml
<? xml version="1.0" ?> <! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <!-- Generated 2017-3-1 20:42:49 by Hibernate Tools 3.5.0.Final --> < hibernate-mapping > < class name ="com.third.Dao1.Students1" table ="STUDENTS1" > < id name ="sid" type ="int" > < column name ="SID" /> < generator class ="assigned" /> </ id > < property name ="sname" type ="java.lang.String" > < column name ="SNAME" /> </ property > < property name ="sgender" type ="java.lang.String" > < column name ="SGENDER" /> </ property > </ class > </ hibernate-mapping >
Grader1.cfg.xml
<? xml version="1.0" ?> <! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <!-- Generated 2017-3-1 20:42:49 by Hibernate Tools 3.5.0.Final --> < hibernate-mapping > < class name ="com.third.Dao1.Grader1" table ="GRADER1" > < id name ="gid" type ="int" > < column name ="GID" /> < generator class ="increment" /> </ id > < property name ="gname" type ="java.lang.String" > < column name ="GNAME" /> </ property > < set name ="stuSet" inverse ="false" table ="STUDENTS1" lazy ="true" > < key > < column name ="GID" /> </ key > < one-to-many class ="com.third.Dao1.Students1" /> </ set > </ class > </ hibernate-mapping >
测试文件:
Test.java
1 package com.third; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import org.hibernate.Session; 7 import org.hibernate.SessionFactory; 8 import org.hibernate.Transaction; 9 import org.hibernate.cfg.Configuration; 10 import org.hibernate.service.ServiceRegistry; 11 import org.hibernate.service.ServiceRegistryBuilder; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 16 import com.third.Dao1.Grader1; 17 import com.third.Dao1.Students1; 18 19 /* import com.third.Dao.Grader; 20 import com.third.Dao.Students; */ 21 public class Test1 { 22 23 private static SessionFactory sessionFactory; 24 private static Session session; 25 private static Transaction transaction; 26 @Before 27 public void init(){ 28 // 创建配置对象,匹配读取hibernate.cfg.xml文件 29 Configuration config=new Configuration().configure(); 30//获取服务注册对象(该对象中封装了hibernate.cfg.xml文件中的<properties>、<mapping>信息)31 ServiceRegistry serviceRegistry=new ServiceRegistryBuilder() 32 .applySettings(config.getProperties()).buildServiceRegistry(); 33//获取sessionFactory对象(该对象中通过传参serviceRegistry对象,获取了<mapping><properties>信息)34 sessionFactory=config.buildSessionFactory(serviceRegistry); 35 }5556 @Test 57publicvoid test2(){ 58//通过sessionFactory对象获取session对象59 session=sessionFactory.openSession(); 60//通过session对象开启事务,并返回Transaction对象61 transaction=session.beginTransaction(); 6263//创建students和Grader对象64 Students1 student2=new Students1(); 65 student2.setSname("小美"); 66 student2.setSgender("女"); 67 Students1 student3=new Students1(); 68 student3.setSname("小宏"); 69 student3.setSgender("女"); 7071 Set<Students1> stuSet=new HashSet<Students1>(); 72 stuSet.add(student2); 73 stuSet.add(student3); 7475//实例Grader对象76 Grader1 grader2=new Grader1(); 77 grader2.setGname("信息与计算科学二班"); 78 grader2.setStuSet(stuSet);; 798081 session.save(student2); 8283 session.save(student3); 84 session.save(grader2); 85 } 86 @After 87publicvoid destory(){ 88//提交事务89 transaction.commit(); 90//关闭资源91if(session!=null){ 92 session.close(); 93 } 94if(sessionFactory!=null){ 95 sessionFactory.close(); 96 } 97 } 98 }
下面是报错的报文:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.third.Dao1.Students1#0]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:179)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:206)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:191)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:764)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:756)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:752)
at com.third.Test1.test2(Test1.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
原因分析:
第一步:
报错报文中我们重点看加红的两行信息,第一行:
a different object with the same identifier value was already associated with the session: [com.third.Dao1.Students1#0]
大致的意思说:一个不同的Object对象和session:[com.third.Dao1.Students1#0]中已有的一个对象拥有着相同的唯一辨识符。我们仔细看这段代码,这段代码的主要作用是向Mysql数据库中创建两个关联表格,并且向表中添加一些信息。我们在分析一下这个报错是在我们编写的哪行代码执行不下去了之后,然后抛出异常。
第二步:
很明显:at com.third.Test1.test2(Test1.java:83)
这行错误报文指出我们是在Test1.java代码的83行抛出的异常,我们找到这行代码:session.save(student3);分析这行代码具体执行情况,在这之前只有session.save(students2);代码对session:[com.third.Dao1.Students1#0]操作,这样我们就将这两行代码结合在一起分析。之前说报错的原因是:session:[com.third.Dao1.Students1#0]中已有的对象的唯一标识符和新添加的对象相同,从而产生冲突。而session:[com.third.Dao1.Students1#0]中之前只有代码session.save(students2);对它进行了操作,也就是session:[com.third.Dao1.Students1#0]中只添加了studnets2这一个对象,这样要新添加的对象students3就和students2对象在唯一标识符上冲突。
第三步:
我们打开Navicat for MySQL软件,查看已经由eclipse创建的表格students1的表格结构(通过点击students1表格右键,选择设计表)
很明显表格students1记录的主键是SID,即在session:[com.third.Dao1.Students1#0]中的唯一表示符就是sid,那么我们看看表格中已有的students2的对象记录的主键:
我们能够看到students1表格中有一条SID为0的SNAME为小美的记录,我们可以知道session:[com.third.Dao1.Students1#0]中students2对象的唯一标识符sid为0,而students3对象唯一标识符和它相同冲突,这样students3对象的唯一表示符也将是sid为0。
第四步:
然后我们需要思考,为什么两个对象的唯一标识符都为0,这样我们就需要回到Test1.java代码中去分析,看看对于这个唯一标识符是如何设置的,即查看students2.setSid()和students3.setSid()函数的调用赋值情况。我们在查看完@Test代码段的代码发现,整段代码没有调用students2.setSid()和students3.setSid()函数,当时在设计这个程序时,想法是将主键SID交由MySQL数据库自行递增。所以自己写的代码段就没有对sid进行set赋值。但是MySQL数据库并没有完成主键SID的自动赋值(之前说students2和students3对象的唯一标识符sid都为0,在数据库表格中表现为主键SID都为0),这里就需要讨论数据库的主键的生成策略,而主键的生成策略是由.hbm.xml文件中指定的,这样我们就需要分析Students1.hbm.xml代码,其中控制主键生成策略的是<generator class="" />标签,我们很快找到了这个标签,查看这个标签主键生成策略的设置情况:
我们能看到这里设置的主键生成策略是assigned,而assigned适用于自然主键,由Java应用程序负责生成标识符,也就是说需要我们手动使用setSid()函数手动赋值。而我们并没有进行手动set赋值,而MySQL数据库在assirned主键生成策略下,如果不进行手动set赋值,其主键SID的值将会采取默认的值0,这就解释了唯一标识符sid都是0的冲突问题。
解决方法:(给出两种)
1、修改Students1.hbm.xml代码,其他代码不需要改变:
<? xml version="1.0" ?> <! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <!-- Generated 2017-3-1 20:42:49 by Hibernate Tools 3.5.0.Final --> < hibernate-mapping > < class name ="com.third.Dao1.Students1" table ="STUDENTS1" > < id name ="sid" type ="int" > < column name ="SID" /> < generator class ="increment" /> </ id > < property name ="sname" type ="java.lang.String" > < column name ="SNAME" /> </ property > < property name ="sgender" type ="java.lang.String" > < column name ="SGENDER" /> </ property > </ class > </ hibernate-mapping >
修改的代码是绿色背景的代码,将主键生成策略改成increment(适用于代理主键,由hibernate自动递增方式生成)或者改成native(适用于代理主键,根据底层数据库对自动生成标识符的方式自动选择,其中MySQL是自动递增方式生成)。
2、修改Test1.java代码,其他代码不需要改动。
1 package com.third; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import org.hibernate.Session; 7 import org.hibernate.SessionFactory; 8 import org.hibernate.Transaction; 9 import org.hibernate.cfg.Configuration; 10 import org.hibernate.service.ServiceRegistry; 11 import org.hibernate.service.ServiceRegistryBuilder; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 16 import com.third.Dao1.Grader1; 17 import com.third.Dao1.Students1; 18 19 /* import com.third.Dao.Grader; 20 import com.third.Dao.Students; */ 21 public class Test1 { 22 23 private static SessionFactory sessionFactory; 24 private static Session session; 25 private static Transaction transaction; 26 @Before 27 public void init(){ 28 // 创建配置对象,匹配读取hibernate.cfg.xml文件 29 Configuration config=new Configuration().configure(); 30//获取服务注册对象(该对象中封装了hibernate.cfg.xml文件中的<properties>、<mapping>信息)31 ServiceRegistry serviceRegistry=new ServiceRegistryBuilder() 32 .applySettings(config.getProperties()).buildServiceRegistry(); 33//获取sessionFactory对象(该对象中通过传参serviceRegistry对象,获取了<mapping><properties>信息)34 sessionFactory=config.buildSessionFactory(serviceRegistry); 35 } 363738 @Test 39publicvoid test2(){ 40//通过sessionFactory对象获取session对象41 session=sessionFactory.openSession(); 42//通过session对象开启事务,并返回Transaction对象43 transaction=session.beginTransaction(); 4445//创建students和Grader对象46 Students1 student2=new Students1(); 47 student2.setSname("小美"); 48 student2.setSgender("女"); 49 student2.setSid(1); 50 Students1 student3=new Students1(); 51 student3.setSname("小宏"); 52 student3.setSgender("女"); 53student3.setSid(2); 5455 Set<Students1> stuSet=new HashSet<Students1>(); 56 stuSet.add(student2); 57 stuSet.add(student3); 5859//实例Grader对象60 Grader1 grader2=new Grader1(); 61 grader2.setGname("信息与计算科学二班"); 62 grader2.setStuSet(stuSet);; 636465 session.save(student2); 6667 session.save(student3); 68 session.save(grader2); 69 } 70 @After 71publicvoid destory(){ 72//提交事务73 transaction.commit(); 74//关闭资源75if(session!=null){ 76 session.close(); 77 } 78if(sessionFactory!=null){ 79 sessionFactory.close(); 80 } 81 } 82 }
添加绿色背景的两段代码,手动的添加唯一标识符的值。
总结:
出现a different object with the same identifier value was already associated with the session的错误的原因是session中的对象的唯一标识符相同的冲突,其根本就是表现在数据库中的表格中的主键值相同的冲突或者其他唯一标识符冲突。解决这个冲突,我们必须知道,到底是哪个唯一标识符冲突,然后再去修改掉相同的标识符,让他们值不再相同,这样问题就解决了~
原文:http://www.cnblogs.com/xiaotiaosi/p/6489573.html
内容总结
以上是互联网集市为您收集整理的hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法全部内容,希望文章能够帮你解决hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。