Hibernate异常: a different object with the same identifier value was already associated with the sessi

异常1:org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 
异常2:org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [prework.suzhou.pojos.Book#12]


@Test 
    public void test(){    
        Book book1 = new Book(); 
        book1.setBookName("傲慢与偏见"); 
        //book1.setBookId(12l); 
        Book book2 = new Book(); 
        book2.setBookName("哈姆雷特"); 
        //book2.setBookId(12l); 
        List books = new ArrayList(); 
        books.add(book1); 
        books.add(book2);

        ResourceEntity entity = new ResourceEntity(); 
        entity.setResourceEntityName("外国文学"); 
        entity.setBooks(books); 
        Session session = sf.getCurrentSession(); 
        session.beginTransaction();

        //session.save(book1); ……………………….1 
        //session.save(book2);………………………..2 
        session.save(entity); 
        session.flush(); 
        session.getTransaction().commit();

    }

 

在保存ResourceEntity时级联保存book1。如果级联保存,而book1,book2有一个或两个都设置了id,那么会报第一个异常。

如果book1,book2都设置了id且相等,那么就会报告著名的异常 a different object with the same identifier value was already associated with the session 。为什么说著名,因为这个异常对于初学者来说太常见了,而且很难解决。

网上有一些解决方法,比如merge(),session.clear()…….。其实这些方法并不是很好的解决方案,反而有点蒙蔽自己双眼的感觉。

用merge()是可以的,

Hibernate: insert into ResourceEntity (parentNodeId, resourceEntityName) values (?, ?) 
Hibernate: select book0_.bookId as bookId0_0_, book0_.bookName as bookName0_0_ from Book book0_ where book0_.bookId=? 
Hibernate: insert into Book (bookName) values (?) 
Hibernate: select book0_.bookId as bookId0_0_, book0_.bookName as bookName0_0_ from Book book0_ where book0_.bookId=? 
Hibernate: insert into Book (bookName) values (?) 
Hibernate: insert into ResourceEntity_Book (ResourceEntity_resourceEntityId, books_bookId) values (?, ?) 
Hibernate: insert into ResourceEntity_Book (ResourceEntity_resourceEntityId, books_bookId) values (?, ?)

但是Hibernate对于有疑问的book表会先去查,再插入(merge的时候,hibernate对于级联操作时,被级联的对象如果设置了id,会对其先做select操作)。

其实出现这个问题的原因就是两个book的id设置为一样的,而且又是级联插入!级联的save,两个book对象会同时纳入session管理,出现了相同的id,所以就报错了。

如果我一个一个save(),不级联,book1,book2的id不管怎么设置都无效,hibernate会根据你数据库分配的id分别重新设置book1,book2的id,所以它们的id是不会重的。

所以我们完全可以避开这个异常,对于要级联插入的实体,它们的id是数据库分配的。我们只要避免为它们分配id,就可以避免以上两个异常。如果不可避免的有id,那个在保存前setId(null)就不会出错了。

其实这个问题还是要归结到session的管理方式上~~

你可能感兴趣的:(Hibernate,异常)