Hibernate 为什么以下代码在org.springframework.dao.DuplicateKeyException中失败

Hibernate 为什么以下代码在org.springframework.dao.DuplicateKeyException中失败,hibernate,grails,gorm,Hibernate,Grails,Gorm,以下代码在带有的最后一行失败 //following code is executed from non-transactional service Member member = Member.get(1) try{ Member.withNewTransaction { throw new RuntimeException("error") } }catch(Exception e) { //handle exception } member.user

以下代码在带有的最后一行失败

//following code is executed from non-transactional service
Member member = Member.get(1)
try{
    Member.withNewTransaction {
        throw new RuntimeException("error")
    }
}catch(Exception e) {
    //handle exception
}
member.username = "Fred"
member.save()
我不认为这段代码会失败,因为异常会导致TX回滚,但它被捕获,因此流会传递到下一个语句。实际情况是,从发生异常和回滚的点开始,任何后续保存都会失败,并出现
DuplicateKeyException

我认为这与hibernate会话有关,当回滚发生时,hibernate会话会被破坏,并且hibernate无法再持久化任何附加到此会话的内容(错误是误导性的)

有人能更详细地解释一下到底发生了什么,以及处理这起案件的最佳做法是什么吗?

到目前为止,我找到了3种解决方案:

解决方案#1-将事务置于其自己的会话中

org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session: [com.test.Member#1]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.test.Member#1]
解决方案#2-在回滚发生后重新选择成员

Member.withNewSession {
    Member.withNewTransaction {
        throw new RuntimeException("error")
    }
}
解决方案#3启动主事务

member = Member.get(member.id)
member.username = "Fred"
member.save()
Member.withTransaction {
    Member member = Member.get(1)
    try {
        Member.withNewTransaction {
            throw new RuntimeException("error")
        }
    } catch(Exception e) {
        //handle exception
    }
    member.username = "Fred"
    member.save()
}