代码如下:

    /**
     * 测试4:新增一个秘书角色,并赋给张三该角色
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        
        /******S  开始业务逻辑*************/
        //get方法获取的对象都是持久态
        Role r1 = new Role();
        r1.setRole_name("秘书");
        User user = session.get(User.class,1l);
        user.getRoles().add(r1);
        
        session.update(user);
        /******E  开始业务逻辑*************/
        
        tx.commit();
    }

报错如下:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.qlq.domain.Role
    at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:279)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:455)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:144)
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:888)
    at org.hibernate.persister.collection.AbstractCollectionPersister.insertRows(AbstractCollectionPersister.java:1545)
    at org.hibernate.action.internal.CollectionUpdateAction.execute(CollectionUpdateAction.java:85)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
    at cn.qlq.relation.Many2Many.test4(Many2Many.java:103)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

 

错误解释:

   大概的错误意思是: 游离态对象异常,对象引用了一个未保存的游离态对象,在保存对象之前请先保存游离态对象。

原因:

  大概是新建的Role对象未调用save方法,所以该对象还是游离态,但是已经将该对象与user建立关联,所以在更新user的时候报错。

 解决办法: 

  调用save方法将r1置为持久态。其实最后一句session.update(user)可写可不写,因为get获取的对象本来就处于永久态。

    /**
     * 测试4:新增一个秘书角色,并赋给张三该角色
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        
        /******S  开始业务逻辑*************/
        //get方法获取的对象都是持久态
        Role r1 = new Role();
        r1.setRole_name("秘书");
        User user = session.get(User.class,1l);
        user.getRoles().add(r1);
        
        session.save(r1);
        session.update(user);
        /******E  开始业务逻辑*************/
        
        tx.commit();
    }

 

【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】