当我试图在一些删除操作后进行读取时,我得到了这个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
中获取的PersistenceContextSession 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)
我得到这个错误,因为我试图save
的session
与实体的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