【问题标题】:Hibernate: More than one row with the given identifier was found error休眠:发现给定标识符的多行错误
【发布时间】:2014-06-13 17:05:00
【问题描述】:

我使用的是 spring 4.0.5 和 hibernate 4.3.5;我遇到了休眠错误,我不知道我错在哪里(因为我确定我错了)。我有一个与自身相关的表,它代表一个网络树,其中每个根节点可以有多个子节点,所以我创建了这个类:

@DynamicUpdate
@Cache(region = "it.eng.angelo.spring.dao.hibernate.models.WebTree", usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@Table(name = "MEDIA_GALL_TREE", indexes = {@Index(name = "NOME_FOLDER_IDX", columnList = "NOME_FOLDER")})
public class WebTree extends AbstractModel
{

    private static final long serialVersionUID = -4572195412018767502L;
    private long id;
    private String text;
    private boolean opened;
    private boolean disabled;
    private boolean selected;
    private Set<WebTree> children = new HashSet<WebTree>(0);
    private Set<Media> media = new HashSet<Media>(0);
    private WebTree father;
    private WcmDomain dominio;
    public WebTree()
    {
        super();
    }
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID_FOLDER", unique = true, nullable = false)
    public long getId()
    {
        return id;
    }
    public void setId(long id)
    {
        this.id = id;
    }
    @Column(name = "NOME_FOLDER", nullable = false, unique=false)
    public String getText()
    {
        return text;
    }
    public void setText(String text)
    {
        this.text = text;
    }
    @Column(name = "OPENED_FOLDER")
    public boolean isOpened()
    {
        return opened;
    }
    public void setOpened(boolean opened)
    {
        this.opened = opened;
    }
    @Column(name = "DISABLED_FOLDER")
    public boolean isDisabled()
    {
        return disabled;
    }
    public void setDisabled(boolean disabled)
    {
        this.disabled = disabled;
    }
    @Column(name = "SELECTED_FOLDER")
    public boolean isSelected()
    {
        return selected;
    }
    public void setSelected(boolean selected)
    {
        this.selected = selected;
    }
    @OneToMany(mappedBy = "father", orphanRemoval = true, targetEntity = WebTree.class)
    public Set<WebTree> getChildren()
    {
        return children;
    }
    public void setChildren(Set<WebTree> children)
    {
        this.children = children;
    }
    @ManyToOne(targetEntity = WebTree.class)
    @JoinColumn(name = "ID_PADRE", nullable = true)
    public WebTree getFather()
    {
        return father;
    }
    public void setFather(WebTree father)
    {
        this.father = father;
    }
    @OneToOne
    @JoinColumn(name="ID_DOMINIO", nullable=false)
    public WcmDomain getDominio()
    {
        return dominio;
    }
    public void setDominio(WcmDomain dominio)
    {
        this.dominio = dominio;
    }
    @OneToMany( mappedBy = "folder", orphanRemoval = true, targetEntity = Media.class, cascade = { CascadeType.ALL })
    public Set<Media> getMedia()
    {
        return media;
    }
    public void setMedia(Set<Media> media)
    {
        this.media = media;
    }

}

如您所见...这是一个非常简单的 POJO 类;现在我创建了这个单元测试:

@Test
public void testLoadModifyTree()
{
    try
    {
        DetachedCriteria dc = DetachedCriteria.forClass(MediaGalleryTree.class);
        dc.setFetchMode("father", FetchMode.JOIN);
        dc.add(Property.forName("id").eq(4l));
        List<MediaGalleryTree> result = hibSvc.search(dc, IConstants.NO_PAGINATION, IConstants.NO_PAGINATION);
        for (MediaGalleryTree mediaGalleryTree : result)
        {
            logger.info(mediaGalleryTree.getId());
        }
    }
    catch (Exception e)
    {
        logger.error(e.getMessage(), e);
    }
}

好吧,我检查了一下,在数据库中我只有 1 条 ID 为 4 的记录;好吧,当我执行此查询时,出现以下错误:

18:48:43,123 ERROR [WcmHibernateDao] Errore nella ricerca con detached criteria DetachableCriteria(CriteriaImpl(it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree:this[][id=4])); More than one row with the given identifier was found: 2, for class: it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree
org.hibernate.HibernateException: More than one row with the given identifier was found: 2, for class: it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree
    at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:100)
    at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:161)
    at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2385)
    at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:767)
    at org.hibernate.type.EntityType.resolve(EntityType.java:505)
    at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
    at org.hibernate.loader.Loader.doQuery(Loader.java:920)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
    at org.hibernate.loader.Loader.doList(Loader.java:2553)
    at org.hibernate.loader.Loader.doList(Loader.java:2539)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
    at org.hibernate.loader.Loader.list(Loader.java:2364)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1682)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
    at it.eng.comi.spring.dao.WcmHibernateDao.searchEntity(WcmHibernateDao.java:140)
    at it.eng.comi.spring.service.impl.WcmRdbmsExtSvcImpl.search(WcmRdbmsExtSvcImpl.java:237)
    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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy45.search(Unknown Source)
    at it.eng.comi.test.ComiTests.testLoadModifyTree(ComiTests.java:578)
    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:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
18:48:43,135 ERROR [WcmRdbmsExtSvcImpl] Errore nella ricerca con deatchedCriteria DetachableCriteria(CriteriaImpl(it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree:this[][id=4])); Errore nella ricerca con detached criteria DetachableCriteria(CriteriaImpl(it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree:this[][id=4])); More than one row with the given identifier was found: 2, for class: it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree
it.eng.comi.exception.CoMiDbException: Errore nella ricerca con detached criteria DetachableCriteria(CriteriaImpl(it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree:this[][id=4])); More than one row with the given identifier was found: 2, for class: it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree
    at it.eng.comi.spring.dao.WcmHibernateDao.searchEntity(WcmHibernateDao.java:146)
    at it.eng.comi.spring.service.impl.WcmRdbmsExtSvcImpl.search(WcmRdbmsExtSvcImpl.java:237)
    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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy45.search(Unknown Source)
    at it.eng.comi.test.ComiTests.testLoadModifyTree(ComiTests.java:578)
    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:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.HibernateException: More than one row with the given identifier was found: 2, for class: it.eng.comi.spring.dao.hibernate.models.MediaGalleryTree
    at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:100)
    at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:161)
    at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2385)
    at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:767)
    at org.hibernate.type.EntityType.resolve(EntityType.java:505)
    at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
    at org.hibernate.loader.Loader.doQuery(Loader.java:920)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
    at org.hibernate.loader.Loader.doList(Loader.java:2553)
    at org.hibernate.loader.Loader.doList(Loader.java:2539)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
    at org.hibernate.loader.Loader.list(Loader.java:2364)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1682)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
    at it.eng.comi.spring.dao.WcmHibernateDao.searchEntity(WcmHibernateDao.java:140)
    ... 43 more

当代码执行时,休眠打印这些查询:

Hibernate: 
    select
        this_.ID_FOLDER as ID_FOLDE1_7_2_,
        this_.UT_INS as UT_INS2_7_2_,
        this_.DT_INS as DT_INS3_7_2_,
        this_.DT_UPD as DT_UPD4_7_2_,
        this_.UT_UPD as UT_UPD5_7_2_,
        this_.DISABLED_FOLDER as DISABLED6_7_2_,
        this_.ID_DOMINIO as ID_DOMI10_7_2_,
        this_.ID_PADRE as ID_PADR11_7_2_,
        this_.OPENED_FOLDER as OPENED_F7_7_2_,
        this_.SELECTED_FOLDER as SELECTED8_7_2_,
        this_.NOME_FOLDER as NOME_FOL9_7_2_,
        wcmdomain2_.ID_DOMINIO as ID_DOMIN1_8_0_,
        wcmdomain2_.UT_INS as UT_INS2_8_0_,
        wcmdomain2_.DT_INS as DT_INS3_8_0_,
        wcmdomain2_.DT_UPD as DT_UPD4_8_0_,
        wcmdomain2_.UT_UPD as UT_UPD5_8_0_,
        wcmdomain2_.WCM_NOME_DOMINIO as WCM_NOME6_8_0_,
        mediagalle3_.ID_FOLDER as ID_FOLDE1_7_1_,
        mediagalle3_.UT_INS as UT_INS2_7_1_,
        mediagalle3_.DT_INS as DT_INS3_7_1_,
        mediagalle3_.DT_UPD as DT_UPD4_7_1_,
        mediagalle3_.UT_UPD as UT_UPD5_7_1_,
        mediagalle3_.DISABLED_FOLDER as DISABLED6_7_1_,
        mediagalle3_.ID_DOMINIO as ID_DOMI10_7_1_,
        mediagalle3_.ID_PADRE as ID_PADR11_7_1_,
        mediagalle3_.OPENED_FOLDER as OPENED_F7_7_1_,
        mediagalle3_.SELECTED_FOLDER as SELECTED8_7_1_,
        mediagalle3_.NOME_FOLDER as NOME_FOL9_7_1_ 
    from
        MEDIA_GALL_TREE this_ 
    inner join
        WCM_DOMAIN wcmdomain2_ 
            on this_.ID_DOMINIO=wcmdomain2_.ID_DOMINIO 
    left outer join
        MEDIA_GALL_TREE mediagalle3_ 
            on this_.ID_PADRE=mediagalle3_.ID_FOLDER 
    where
        this_.ID_FOLDER=?
Hibernate: 
    select
        mediagalle0_.ID_FOLDER as ID_FOLDE1_7_2_,
        mediagalle0_.UT_INS as UT_INS2_7_2_,
        mediagalle0_.DT_INS as DT_INS3_7_2_,
        mediagalle0_.DT_UPD as DT_UPD4_7_2_,
        mediagalle0_.UT_UPD as UT_UPD5_7_2_,
        mediagalle0_.DISABLED_FOLDER as DISABLED6_7_2_,
        mediagalle0_.ID_DOMINIO as ID_DOMI10_7_2_,
        mediagalle0_.ID_PADRE as ID_PADR11_7_2_,
        mediagalle0_.OPENED_FOLDER as OPENED_F7_7_2_,
        mediagalle0_.SELECTED_FOLDER as SELECTED8_7_2_,
        mediagalle0_.NOME_FOLDER as NOME_FOL9_7_2_,
        wcmdomain1_.ID_DOMINIO as ID_DOMIN1_8_0_,
        wcmdomain1_.UT_INS as UT_INS2_8_0_,
        wcmdomain1_.DT_INS as DT_INS3_8_0_,
        wcmdomain1_.DT_UPD as DT_UPD4_8_0_,
        wcmdomain1_.UT_UPD as UT_UPD5_8_0_,
        wcmdomain1_.WCM_NOME_DOMINIO as WCM_NOME6_8_0_,
        mediagalle2_.ID_FOLDER as ID_FOLDE1_7_1_,
        mediagalle2_.UT_INS as UT_INS2_7_1_,
        mediagalle2_.DT_INS as DT_INS3_7_1_,
        mediagalle2_.DT_UPD as DT_UPD4_7_1_,
        mediagalle2_.UT_UPD as UT_UPD5_7_1_,
        mediagalle2_.DISABLED_FOLDER as DISABLED6_7_1_,
        mediagalle2_.ID_DOMINIO as ID_DOMI10_7_1_,
        mediagalle2_.ID_PADRE as ID_PADR11_7_1_,
        mediagalle2_.OPENED_FOLDER as OPENED_F7_7_1_,
        mediagalle2_.SELECTED_FOLDER as SELECTED8_7_1_,
        mediagalle2_.NOME_FOLDER as NOME_FOL9_7_1_ 
    from
        MEDIA_GALL_TREE mediagalle0_ 
    inner join
        WCM_DOMAIN wcmdomain1_ 
            on mediagalle0_.ID_DOMINIO=wcmdomain1_.ID_DOMINIO 
    left outer join
        MEDIA_GALL_TREE mediagalle2_ 
            on mediagalle0_.ID_PADRE=mediagalle2_.ID_FOLDER 
    where
        mediagalle0_.ID_DOMINIO=?

这些是我的表格记录:

id_folder; ut_ins; dt_ins; dt_upd; ut_upd; disabled_folder; opened_folder; selected_folder; nome_folder; id_dominio; id_padre
"1";"system";"2014-06-12 18:23:16.649";"2014-06-12 18:23:16.649";"system";FALSE;FALSE;FALSE;"Root 1";1;
"2";"system";"2014-06-12 18:23:16.662";"2014-06-12 18:23:16.662";"system";FALSE;FALSE;FALSE;"Root 2";2;
"4";"wpsAdmin";"2014-06-13 16:18:01.428";"2014-06-13 18:12:14.228";"wpsAdmin";FALSE;FALSE;FALSE;"Testina";2;2
"7";"wpsAdmin";"2014-06-13 17:33:05.575";"2014-06-13 17:33:10.275";"wpsAdmin";FALSE;FALSE;FALSE;"Angelo";2;2

谁能告诉我哪里错了?在我看来一切都是正确的......欢迎任何提示

谢谢 安杰洛

请注意:如果我以这种方式更改我的 POJO 类方法 getChildern,一切都会很好:

@OneToMany( mappedBy = "father", targetEntity = WebTree.class, fetch=FetchType.EAGER)
public Set<WebTree> getChildren()
{
    return children;
}

但我想知道为什么会出现这种行为?

谢谢 安杰洛

【问题讨论】:

  • 你解决了吗?好像我在我的情况下找不到这个异常的原因..
  • @GiorgiTsiklauri 广告我说,这是我在 hbernate 映射中的错误...如果您需要帮助,您可以使用一些代码发布问题,我会尝试调查...
  • 我有同样的问题,你能帮帮我吗?我在一对一映射上遇到了问题
  • 您遇到了哪种问题?也许打开一个问题并输入一些代码会更好:)

标签: hibernate


【解决方案1】:

我被org.hibernate.HibernateException: More than one row with the given identifier was found: 问题所困扰,在 StackOverflow 上找不到任何帮助。解决问题需要一段时间,所以我在这里记录解决方案。我使用的是 JPA/Hibernate 和 Spring Data。

首先,这不是由数据库中的重复行引起的,因为显然不可能有重复的主键。相反,这是由 Hibernate 查找对象并急切地使用 LEFT OUTER JOIN 填充一对一关系引起的。 Hibernate 假设会返回一行,但返回两行是因为有两个对象与一对一关系相关联。

这是我的对象的简化版本:

@Entity
@Table(name = "plate")
public class Plate {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="test_seq", sequenceName="test_seq")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "test_seq")
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "object_version")
    private long objectVersion;

    @Column(name = "name")
    private String name;

    @OneToOne(mappedBy = "plate")
    private Sheet sheet;

    public Sheet getSheet() {
        return sheet;
    }

    public void setSheet(Sheet sheet) {
        if (this.sheet != null) {
            this.sheet.setPlate(null);
        }

        this.sheet = sheet;
        sheet.setPlate(this);
    }
}


@Entity
@Table(name = "sheet")
public class Sheet {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="test_seq", sequenceName="test_seq")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "test_seq")
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "object_version")
    private long objectVersion;

    @Column(name = "sheet_name")
    private String sheetName;

    @OneToOne
    @JoinColumn(name = "plate_id")
    private Plate plate;

    public Plate getPlate() {
        return plate;
    }

    // Do not use. Use Plate.setSheet() instead
    void setPlate(Plate plate) {
        this.plate = plate;
    }
}

问题在于 Plate 和 Sheet 之间的@OneToOne 关系。我最初不想删除孤立的表格。在我的代码中,我通过 id 查找了一个 Plate 并添加了一个新工作表。这从原始图纸中删除了板到图纸的关系。当我提交事务时,我假设 JPA 会保存所有修改过的对象(Plate、原始 Sheet 和新 Sheet)。

这不是真的! JPA 显然是通过从最初加载的对象(Plate)向下遍历层次结构来查找修改的对象,并且它错过了现在孤立的原始 Sheet 已被修改的事实。这意味着原始工作表的 sheet.plate_id 列未在数据库中清除。换句话说,我在数据模型中破坏了它们的关系,但它未能保存到数据库中。所以下次我尝试加载板时,Hibernate 会运行如下查询:

select
    plate1_.id as id1_19_12_, 
    plate1_.object_version as object_v2_19_12_, 
    plate1_.name as name3_19_12_, 
    sheet2_.id as id1_39_12_, 
    sheet2_.object_version as object_v2_39_12_, 
    sheet2_.sheet_name as sheet_nam2_39_12_, 
    sheet2_.plate_id as plate_id4_39_12_, 
from 
    plate plate1_
    left outer join sheet sheet2_ on plate1_.id = sheet2_.plate_id
where 
    plate1_.id=?

这会在结果集中返回 2 行并产生此错误:

org.hibernate.HibernateException: More than one row with the given identifier was found: 10045, for class: com.example.Plate

这是欺骗性的:数据库中只有一个具有该 ID 的 Plate 行,但有两个 Sheets 链接到它。

解决办法: 似乎我有两个选择:要么全部级联并删除一对一关系上的孤儿,要么每次删除与 Plate 的关系时显式调用我的存储库类来查找并保存原始工作表。我选择了第一个选项并将其添加到板类中:

@OneToOne(mappedBy = "plate", cascade = CascadeType.ALL, orphanRemoval = true)
private Sheet sheet;

这解决了问题。

【讨论】:

  • 这也是我的情况。我已经开始在数据库中为这些 OneToOne 关系添加独特的约束,因为这样会在开发的早期发现类似的问题。
  • 我遇到了同样的问题,不幸的是,cascade all 和 delete orphan 对我不起作用:(
  • 我也是..请有人帮助我们!
【解决方案2】:

对不起;这是我的错误......在我的实体类中,我错误地将关系映射为 oneToOne;相反,它是 oneToMany :) 现在一切都很好......;这是我的新实体类:

@DynamicUpdate
@Cache(region = "it.eng.angelo.spring.dao.hibernate.models.MediaGalleryTree", usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@Table(name = "MEDIA_GALL_TREE", indexes = {@Index(name = "NOME_FOLDER_IDX", columnList = "NOME_FOLDER")})
public class MediaGalleryTree extends AbstractModel
{

    private static final long serialVersionUID = -4572195412018767502L;
    private long id;
    private String text;
    private boolean opened;
    private boolean disabled;
    private boolean selected;
    private Set<MediaGalleryTree> children = new HashSet<MediaGalleryTree>(0);
    private Set<FedoraCommonsEntity> media = new HashSet<FedoraCommonsEntity>(0);
    private MediaGalleryTree father;
    private WcmDomain dominio;
    public MediaGalleryTree()
    {
        super();
    }
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID_FOLDER", unique = true, nullable = false)
    public long getId()
    {
        return id;
    }
    public void setId(long id)
    {
        this.id = id;
    }
    @Column(name = "NOME_FOLDER", nullable = false, unique=false)
    public String getText()
    {
        return text;
    }
    public void setText(String text)
    {
        this.text = text;
    }
    @Column(name = "OPENED_FOLDER")
    public boolean isOpened()
    {
        return opened;
    }
    public void setOpened(boolean opened)
    {
        this.opened = opened;
    }
    @Column(name = "DISABLED_FOLDER")
    public boolean isDisabled()
    {
        return disabled;
    }
    public void setDisabled(boolean disabled)
    {
        this.disabled = disabled;
    }
    @Column(name = "SELECTED_FOLDER")
    public boolean isSelected()
    {
        return selected;
    }
    public void setSelected(boolean selected)
    {
        this.selected = selected;
    }
    @OneToMany( mappedBy = "father", orphanRemoval = true, 
                targetEntity = MediaGalleryTree.class)
    public Set<MediaGalleryTree> getChildren()
    {
        return children;
    }
    public void setChildren(Set<MediaGalleryTree> children)
    {
        this.children = children;
    }
    @ManyToOne(targetEntity = MediaGalleryTree.class)
    @JoinColumn(name = "ID_PADRE", nullable = true)
    public MediaGalleryTree getFather()
    {
        return father;
    }
    public void setFather(MediaGalleryTree father)
    {
        this.father = father;
    }
    @ManyToOne(targetEntity = WcmDomain.class, cascade={CascadeType.ALL})
    @JoinColumn(name="ID_DOMINIO", nullable=false)
    public WcmDomain getDominio()
    {
        return dominio;
    }
    public void setDominio(WcmDomain dominio)
    {
        this.dominio = dominio;
    }
    @OneToMany( mappedBy = "folder", orphanRemoval = true, 
            targetEntity = Media.class, cascade = { CascadeType.ALL })
    public Set<FedoraCommonsEntity> getMedia()
    {
        return media;
    }
    public void setMedia(Set<FedoraCommonsEntity> media)
    {
        this.media = media;
    }

}

安杰洛

【讨论】:

    【解决方案3】:

    如果你的类中有@OneToOne 映射,则将获取类型更新为 LAZY。 因为默认情况下 OneToOne 的获取类型是 EAGER,所以当我们获取 ma​​in class (WebTree) 类的对象时,它会获取 OneToOne 的对象映射类,所以当休眠映射对象时,它会抛出异常。 简而言之,如果您有 OneToOne 映射,则将其替换为 @OneToOne(fetch = FetchType.LAZY)

    【讨论】:

    • 我遇到了 @OneToMany(fetch = FetchType.LAZY) 的问题。在将获取类型更改为 EAGER 时,问题似乎已经解决。我认为我仍然不清楚根本原因。
    【解决方案4】:

    上述解决方案都不适用于我的情况。我只能通过从双向一对一关系更改为单向一对一关系来使其工作。

    【讨论】:

    • 请多解释一下。你的回答看起来更像是评论
    • @MohammadSadiqurRahman 这意味着您需要从两个对象之一中删除 @OneToOne 注释,他的答案非常清楚,并且该解决方案也对我有用。
    【解决方案5】:

    我遇到了同样的问题,我还将映射从 OneToOne 映射更改为 OneToMany 映射。以前,我错误地将映射定义为 OneToOne。现在它可以正常工作了。

    @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
        @JoinColumn(name="appointmentId", nullable=false, insertable=false, updatable=false)
        private Appointment appointment;
    

    当前

    @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
        @JoinColumn(name="appointmentId", nullable=false, insertable=false, updatable=false)
        private Appointment appointment;
    

    【讨论】:

      【解决方案6】:

      在hibernate-mapping中找到一对一的关系,然后在数据库中的关联表中找到,有可能是关系表得到多行

      【讨论】:

      • 这就是我遇到的问题,我有一个用户表和一个团队,一对一映射。但是,我可以添加多个与映射相反的团队。那是错误第一次出现的时候。我检查了 mysql,是的,团队数据库中有两条记录,那么可能出了什么问题?
      【解决方案7】:

      尝试检查实体关系@OneToOne,在您的情况下检查 WcmDomain 实体,它将包含两个引用 WebTree 的记录。因此,一旦您通过 findById 加载 WebTree,它将失败,因为它正在进行内部连接,最终结果将是两条记录。

      所以从 WcmDomain 中删除多余的记录,它会起作用

      【讨论】:

        【解决方案8】:

        我在更新数据时遇到了同样的问题。我通过传递带有主键的父对象解决了这个问题。所有子对象的主键都设置为空。这对我有用。以上解决方案都不适用于我的情况。

        【讨论】:

          【解决方案9】:

          我遇到了同样的问题,当我执行一个连接了 2 个表但实体不包含来自另一个表的字段的本机查询时。

          经过很多努力,以下解决方案对我有用:

          我只是声明了实体中不存在的必需字段(这些字段也与当前实体所代表的表中不存在的字段相同) 及其 getter 和 setter。

          【讨论】:

          • 我猜你想太多了。因为它是一个原生查询,你可以使用 sql join 从另一个表中获取它,不是吗?
          【解决方案10】:

          我在 2 个实体/类之间的 @OneToOne 映射中遇到了这个问题。 这个问题有两种解决方案:

          1. 如果您不想同时保存两个实体/相同的发布请求,则将 OneToOne 映射关联设为 UNIDIRECTIONAL 并避免双向。

          2. 如果您想使用 Cascade 同时保存这两个实体,则进行 OneToOne 映射 BIDIRECTIONAL 并在您使用 @MappedBy() 的实体/类中使用 @TRANSIENT。

          让我知道它是否有效..

          【讨论】:

            【解决方案11】:

            我遇到了同样的问题。让它成为一个方向对我有用。

            【讨论】:

              【解决方案12】:

              添加@JsonIgnore 并更改级联以获取:

              @Getter
              @Setter
              @OneToOne(fetch = FetchType.LAZY)
              @JoinColumn(name = "capacitacion_id", referencedColumnName = "id")
              @JsonIgnore
              private Capacitacion capacitacion;
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-02-08
                • 1970-01-01
                • 1970-01-01
                • 2020-06-17
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多