我有一个小问题,我不知道该如何解决。请问你能帮帮我吗?当我尝试保留实体时,出现下一个异常:
12:47:39,398 ERROR [org.black.dmitriy.entityHome.ScheduleHome] (http--127.0.0.1-8080-1) javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [org.black.dmitriy.entity.Schedule#1] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1333) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final] at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:859) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_04] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_04] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_04] at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_04] at org.jboss.seam.persistence.EntityManagerInvocationHandler.invoke(EntityManagerInvocationHandler.java:46) [jboss-seam.jar:2.3.0.Final] at $Proxy81.persist(Unknown Source) at org.jboss.seam.framework.EntityHome.persist(EntityHome.java:84) [jboss-seam.jar:2.3.0.Final] at org.black.dmitriy.entityHome.ConversationHome.tryPersist(ConversationHome.java:147) [ejb.jar:] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_04] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_04] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_04] at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_04] at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.core.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:65) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:97) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.util.Work.workInTransaction(Work.java:61) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:186) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:104) [jboss-seam.jar:2.3.0.Final] at org.black.dmitriy.entityHome.ScheduleHome_$$_javassist_seam_8.tryPersist(ScheduleHome_$$_javassist_seam_8.java) [ejb.jar:] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_04] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_04] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_04] at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_04] at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:335) [jboss-el-1.0_02.CR6.jar:1.0_02.CR6] at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:348) [jboss-el-1.0_02.CR6.jar:1.0_02.CR6] at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58) [jboss-el-1.0_02.CR6.jar:1.0_02.CR6] at org.jboss.el.parser.AstValue.invoke(AstValue.java:96) [jboss-el-1.0_02.CR6.jar:1.0_02.CR6] at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276) [jboss-el-1.0_02.CR6.jar:1.0_02.CR6] at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.3.0.Final] at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) [jboss-seam.jar:2.3.0.Final] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:397) [jbossweb-7.0.13.Final.jar:] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:] at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_04]
我使用接缝2.3,进入休眠状态。我的import.sql文件中有一个插入语句:
INSERT INTO Schedules (id, name, dayCount, lessonCount, firstTermSize, secondTermSize, subgroupSize) VALUES(1, '2012/2013', 5, 8, 9, 9, 18)
它在表Schedule中插入一个实体。
然后,我使用EntityHome创建新的Schedule实体投放网页
@Name("scheduleHome") @Scope(ScopeType.CONVERSATION) public class ScheduleHome extends ConversationHome<Schedule> { private static final long serialVersionUID = 1L; public ScheduleHome() { } @Override protected boolean isUnique() { Schedule schedule = getInstance(); Schedule foundSchedule = ScheduleDAO.instance().getByName(schedule.getName()); if ((foundSchedule != null) && (!foundSchedule.equals(schedule))) { showExistsErrorMessage(getInstance().getName()); return false; } return true; } @Override protected Schedule createInstance() { return new Schedule(); } @Override public String getEditOutcome() { return "scheduleEdit"; } @Override protected void prepareEntityForSaving() { } }
和超类
public abstract class ConversationHome<T> extends EntityHome<T> { private static final long serialVersionUID = 1L; private String parentView; public boolean isParentViewExists() { return parentView != null && parentView.length() > 0; } public void setParentView(String parentView) { this.parentView = parentView; } public String getParentView() { return parentView; } public abstract String getEditOutcome(); protected abstract void prepareEntityForSaving(); protected abstract boolean isUnique(); @Override @Create public void create() { create(false); } protected void create(boolean createNestedConversation) { Conversation conversation = Conversation.instance(); if (!createNestedConversation && conversation.isLongRunning()) { getLog().debug("conversation already started, nested will not create(isLongRunning = #0, isNested = #1)", conversation.isLongRunning(), conversation.isNested()); } else { conversation.begin(false, conversation.isLongRunning()); conversation.changeFlushMode(FlushModeType.MANUAL); getLog().debug("create(isLongRunning = #0, isNested = #1, id = #2)", conversation.isLongRunning(), conversation.isNested(), conversation.getId()); } super.create(); } private boolean init(Long id) { FacesContext context = FacesContext.getCurrentInstance(); setParentView(Pages.getViewId(context)); if (id != null) { setId(id); try { getInstance(); getLog().debug("instance initialized #0", getInstance()); } catch (EntityNotFoundException e) { getLog().error(e); return false; } } return true; } public String startEdit(Long id) { getLog().debug("start editing #0", id); if (init(id)) { return getEditOutcome(); } else { return cancel(); } } public String cancel() { if (isManaged()) { getEntityManager().refresh(getInstance()); } return returnToParent(); } @End protected String returnToParent() { if (isParentViewExists()) { Conversation conversation = Conversation.instance(); getLog().debug("end conversation(id = #0, isLongRunning = #1, isNested = #2)", conversation.getId(), conversation.isLongRunning(), conversation.isNested()); conversation.end(true); return getParentView(); } else { clearInstance(); return null; } } public String tryPersist() { if (isUnique()) { try { prepareEntityForSaving(); String outcome = persist(); if (!"failed".equals(outcome)) { return returnToParent(); } } catch (Exception e) { getLog().error(getInstance(), e); showSaveErrorMessage(e); } } return "failed"; } }
当我尝试坚持下去时,我得到了这个例外。和网页上的消息
使用消息保存错误:具有相同标识符值的另一个对象已与该会话关联:[org.black.dmitriy.entity.Schedule#1]
它使休眠将id属性设置为1,但是我已经有了的实体id = 1,因为我手动创建了它,并抛出了import.sql。
id = 1
这是我的Schedule实体:
import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; @Entity @Table(name = "Schedules") public class Schedule { @Id @GeneratedValue @Column(name = "id", nullable = false) private Long id; @NotNull @Column(name = "name", nullable = false, length = 40) private String name; @Column(name = "dayCount") private int dayCount = 5; @Column(name = "lessonCount") private int lessonCount = 8; @Column(name = "firstTermSize") private int firstTermSize = 9; @Column(name = "secondTermSize") private int secondTermSize = 9; @Column(name = "subgroupSize") private int subgroupSize = 18; @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, targetEntity = Faculty.class) private List<Faculty> faculties = new ArrayList<>(); @OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, targetEntity = Building.class) private List<Building> buildings = new ArrayList<>(); public Schedule() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDayCount() { return dayCount; } public void setDayCount(int dayCount) { this.dayCount = dayCount; } public int getLessonCount() { return lessonCount; } public void setLessonCount(int lessonCount) { this.lessonCount = lessonCount; } public int getFirstTermSize() { return firstTermSize; } public void setFirstTermSize(int firstTermSize) { this.firstTermSize = firstTermSize; } public int getSecondTermSize() { return secondTermSize; } public void setSecondTermSize(int secondTermSize) { this.secondTermSize = secondTermSize; } public int getSubgroupSize() { return subgroupSize; } public void setSubgroupSize(int subgroupSize) { this.subgroupSize = subgroupSize; } public List<Faculty> getFaculties() { return faculties; } public void setFaculties(List<Faculty> faculties) { this.faculties = faculties; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Schedule)) { return false; } Schedule other = (Schedule) obj; if (id == null) { if (other.id != null) { return false; } } else if (!id.equals(other.id)) { return false; } return true; } @Override public String toString() { return this.name; } }
如您所见,id属性上有@GeneratedValue批注,所以我认为hibernate应该自己生成id,hibernate应该知道数据库中有id = 1的实体,并在newEntity = 2中设置了id。但是Hibernate设置了id在新实体中加入1.。能否请我停顿一下?
问题是hibernate如何生成您id的,它从1开始。当它将1分配给对象之前,将其保存到数据库中时,它会看到数据库中已经存在具有相同ID的行,并导致异常。这个问题的简单自然的解决方案就是限制休眠,以便它不能1作为ID分配给相关类的任何对象(在您的情况下)。
id
1
mySql的解决方案:
如果使用的是mySql,则可以手动创建表并设置自动增量,例如:
CREATE TABLE IF NOT EXISTS `testTable` ( `id` number(11) NOT NULL AUTO_INCREMENT, ..., ..., ..., PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2; //assigning id by hibernate, will start from 2.
并且在您的域类中,您可以像下面这样对id进行注释:
@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") public long getId() { .... }
GenerationType.AUTO默认情况下,在mySql中使用自动递增。并在设置AUTO_INCREMENT=2休眠状态后开始分配ID的来源2(因此1被跳过)。
GenerationType.AUTO
AUTO_INCREMENT=2
2
Oracle解决方案:
如果您限制休眠使用“序列”,并将序列的初始点设置为您希望的值,则对于oracle可以完成相同的操作。您可以像下面这样创建一个从头开始2并递增的序列1:
create sequence idSequence start with 2 increment by 1 maxvalue 9999999999999;
您可以指定要用来生成域类对象的ID的序列,例如波纹管:
@Id @SequenceGenerator(name = "idGeneratorSeq", sequenceName = "idSequence") @GeneratedValue(strategy = GenerationType.AUTO, generator = "idGeneratorSeq") @Column(name = "ID") public long getId() { .... }
这样您的问题就解决了。