assertionfailure:无法执行取消删除



当我试图在一些删除操作后进行读取时,我得到了这个hibernate断言错误。

我找不到关于这个"无法执行未删除"错误的任何东西,除了源代码,所以我认为,也许我正在做一些如此明显的错误…

堆栈跟踪在下面,

AssertionFailure:43 -  - HHH000099: an assertion failure occured (this may indicate a bug in         Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: Unable     to perform un-delete for instance X
org.hibernate.AssertionFailure: Unable to perform un-delete for instance X
   at org.hibernate.engine.spi.ActionQueue.unScheduleDeletion(ActionQueue.java:508)
   at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:157)
   at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
   at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
   at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
   at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
   at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
   at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
   at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
   at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
   at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:190)
   at org.hibernate.event.internal.DefaultPersistEventListener.entityIsDeleted(DefaultPersistEventListener.java:229)
   at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:158)
   at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
   at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
   at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
   at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
   at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
   at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
   at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
   at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423)
   at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:190)
   at org.hibernate.event.internal.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:183)
   at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:147)
   at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870)
   at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863)
   at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346)
   at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
   at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
   at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
   at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409)
   at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350)
   at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
   at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
   at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
   at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:160)
   at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:151)
   at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
   at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
   at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1186)
   at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1241)
   at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
   at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:257)
   at org.hibernate.ejb.criteria.CriteriaQueryCompiler$3.getResultList(CriteriaQueryCompiler.java:254)

此致敬礼

我也有同样的问题。发生的事情是,我正在删除相关的bean,让我们称它们为A和b。我删除了b,然后继续寻找链接到A的实体C,并将A类型的bean作为查询的参数,进行查询导致了这个Exception。我最好的猜测是,当我删除B时,实体D上的Cascade注释(同时引用a和B)删除了a,然后将已经在DB级别删除的实体作为参数提供给查询,导致了问题。

重新排列代码,以便我首先删除从C到A和的引用,然后继续删除B和A似乎可以解决这个问题。

我今天也遇到了同样的堆栈跟踪,使用Hibernate 4。作为JPA 2。x提供者。以下是我了解到的修复这个引发的异常需要修改的内容。

在我的JPA映射域模型中,我有一个深度的基于OneToMany的图,a有许多B, B有许多C, C有许多D, D有许多e。所有一对多的级联类型都是all。反向指向的ManyToOne存在于每个级别,当这些ManyToOne关系都是默认的(即急切加载)时,我们编写的代码工作得很好

在我今天诊断的令人不快的用例中,我们用JPQL查询读取离散的D集合,当我们迭代该集合时,我们调用EntityManager.remove(c),其中我们通过请求D实例为其父/所有者c实例来获得c实例。

如果该c实例是由D到c关系延迟加载获得的,则调用EntityManager.remove(c)不会报错,但随后调用EntityManager.flush()会导致主题Exception。

如果在JPQL查询中,通过添加"join fetch dc "来急切加载D到C的关系,则不会引发主题Exception。

所以,我想我应该分享这些结果,以防其他人也面临这个问题,上面的内容给了他们一个想法,他们可以改变什么来平息这个问题。

这是给所有通过搜索不能取消删除断言来这里的人(像我一样)。

我在承包商留给我们的一些代码中的断言中遇到了同样的问题,但对我来说,问题不是级联,它工作得很好。

由于某种原因,Hibernate在同一个会话中加载同一个实体两次。我是在深入研究Hibernate内部时才发现这一点的。

我使用org.hibernate.stat.SessionStatistics,您可以从会话中获得和从SessionImpl

中获取的PersistenceContext
Session session = (Session)this.entityManager.unwrap(Session.class);
persistenceContext = ((SessionImpl)session).getPersistenceContext();

查看Hibernate加载了什么。

当我打印出带有

的完整实体列表时
public  void printSessionInfo(String where,HashSet<String> printClasses){
        Log log = Logging.getLog(PersistentSesionInfo.class);
        Session session = (Session)this.entityManager.unwrap(Session.class);
        SessionStatistics stats = session.getStatistics();
        HashMap<String,Counter> entityMap = new HashMap<String,Counter>();
        if(stats!=null){
            log.info("EntityManager #0 has #1 managed entities and #2 collections at #3", getHash(entityManager),stats.getEntityCount(),stats.getCollectionCount(),where);
            List<EntityKey> entities = com.google.common.collect.Lists.newArrayList(stats.getEntityKeys());
            Iterator<EntityKey> iter = entities.iterator();
            while(iter.hasNext()){
                EntityKey ek = iter.next();
                if(entityMap.containsKey(ek.getEntityName())){
                    entityMap.get(ek.getEntityName()).increase();
                }else{
                    entityMap.put(ek.getEntityName(), new Counter());
                }
                if(printClasses!=null && printClasses.contains(ek.getEntityName())){
                    try{
                    Object o = ((HibernateSessionProxy)session).get(ek.getEntityName(), ek.getIdentifier());
                    if(o!=null){
                        log.info("Entity #0 of type #1  id=#2 System hash=#3 object hash #4", o,Hibernate.getClass(o).getSimpleName(),ek.getIdentifier(),Integer.toHexString(System.identityHashCode(o)),Integer.toHexString(o.hashCode()));
                    }
                    }catch(javax.persistence.EntityNotFoundException e ){
                        log.error("Entity #0 with id #1 cannot be found anymore", ek.getEntityName(),ek.getIdentifier());
                    }
                }
            }
            for(Entry<String,Counter> entry : entityMap.entrySet()){
                log.info("Entity #0 count #1", entry.getKey(),entry.getValue());
            }
        }
    }
public class Counter {
        int count = 1;
        public void increase(){
            count++;
        }
        public int getCount(){
            return count;
        }
        public String toString(){
            return String.valueOf(count);
        }
    }

我的实体列在那里,但当我使用

persistenceContext.getEntry(myEntity)

它返回null (entityManager.contains(myEntity)返回true)!

我遍历了persistenceContext.getEntitiesByKey()中的所有EntityKeys(在遍历之前可能需要复制列表)

List<EntityKey> list = new ArrayList<EntityKey>();
list.addAll(persistenceContext.getEntitiesByKey().keySet());

在那里,myEntity的EntityKey在那里,但它指向不同的实例(不同的System.identiyHashCode)。

我必须假设问题最终与实体的equals和hashCode方法有关(正如实体问题经常出现的那样)。我注意到类似的实体实例会有相同的hashCode,即使它们的父实例不同。

我使用'必须假设',因为问题没有马上消失(没有重新启动服务器,因为我使用liverebel)。只有在重启服务器并在Hibernate上启用TRACE之后,问题才会消失。在回滚所有其他调试更改并只留下equals/hashCode方法后,它仍然工作。

所以当你的实体出现奇怪的无法解释的问题时-检查equals和hashCode方法!并使用Hibernate类PersistenceContext和SessionStatistics来调试它。

我知道这是一个很晚的回答,但这可能会帮助某人,在未来的某个时候!这个答案是关于类似的错误(如果有人碰到这个问题,幸运的是):AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)

我得到这个错误,因为我试图savesession与实体的not-null属性-主键被设置为null

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "calc_id", unique = true, nullable = false)
private Long calcId;

GenerationType。在save之前没有设置主键值。和Tadaa……我得到了和前面提到的一样的错误。因此,我将代码替换为以下代码:

@SequenceGenerator(name="identifier", sequenceName="mytable_id_seq", allocationSize=1)  
@GeneratedValua(strategy=GenerationType.SEQUENCE, generator="identifier")

它如果读取(load()代理实例),然后调用delete和save,这可能是hibernate的一个bug。https://hibernate.atlassian.net/browse/HHH-8374

我有同样的错误。我有A班和B班。B有一个a列表,a有一个指向B的引用。A也有一个对对象C (Cascade.All)的引用,该引用在取消删除时导致异常。

我试图将A的对象重新定位到b的另一个对象

这会导致异常:

objectOfA.getObjectOfB().getListOfAs().remove(objectOfA);
objectOfB1.getListOfAs().add(objectOfA);
objectOfA.seObjectOfB(objectOfB1);
dao.flush()

这是有效的解决方案。

objectOfA.seObjectOfB(objectOfB1);
dao.flush()
bjectOfA.getObjectOfB().getListOfAs().remove(objectOfA);
objectOfB1.getListOfAs().add(objectOfA);

最后两行并不总是强制性的,因为hibernate会在重新加载后纠正这一点。

我不知道这是不是休眠中的bug。发生异常是因为hibernate将对象C与ActionQueue.unScheduleDeletion()中带有"=="的相同C的代理进行比较

我也曾经遇到过这个问题。在使用双向映射的情况下,当我们使用多个@OneToMany并使用mappedby注释时,服务器显示这种错误。因此,您可以使用

轻松解决问题。
@JoinTable(name="c",joinColumns=@JoinColumn(name="c_id"),inverseJoinColumns=@JoinColumn(name="l_id"))

而不是使用mapped ..

我使用cascade = CascadeType。所有并且它工作了,假设你从实体A引用的实体B上得到它,请将级联所有放在A上,

还取决于谁在维护关系,在我的例子中,关系是由a映射的。

对于那些到达这个线程并使用Grails的人,我的两分意见。

在我的例子中,问题来自于将域持久属性更改为瞬态属性(提供特定的setter和getter),并使用map版本的构造函数并将变量传递给那里。

最初的域类是这样的:

class MyDomain {
    String content
}

我创建了这样一个实例:

def domain = new MyDomain( content: "sample content" )

更新域:

class MyDomain {
    static transients = [ 'content' ]
    byte[] compressed
    String getContent() {
        compressed ? uncompress( compressed ) : null
    }
    void setContent( String content ) {
        compressed = content ? compress( content ) : null 
    }
}

构造函数不会报错,但是没有调用setContent,奇怪的是,它没有给出验证错误或SQL错误,而是引发这个线程中提到的错误。

解决方案很简单:

def domain = new MyDomain()
domain.content = "sample content"

这样就可以调用setter

最新更新