原本想配置多對多關係(中間表),並把多對多拆分爲兩個一對多以後發現一個問題,在一對多時,子類保存父類時報錯java
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.study.hibernate.domain.TbUser at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:249) at org.hibernate.type.EntityType.getIdentifier(EntityType.java:509) at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:311) at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:321) at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:294) at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:4049) at org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:537) at org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:235) at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:164) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:230) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:100) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1159) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404) at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) at com.study.hibernate.operate.HibernateTest.saveTest3(HibernateTest.java:275) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) 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.runNotIgnored(BlockJUnit4ClassRunner.java:79) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 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:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
配置以下:session
主表:app
<hibernate-mapping> <class name="com.study.hibernate.domain.TbUser" table="tb_user" catalog="db_hibernate" select-before-update="true"> <id name="id" column="id" type="java.lang.Long"> <generator class="native"></generator> </id> <property name="name" column="name" type="java.lang.String"></property> <property name="age" column="age" type="java.lang.Long"></property> <property name="city" column="city" type="java.lang.String"></property> <set name="orders" cascade="save-update,delete-orphan" inverse="true"> <key column="tb_user_id"/> <one-to-many class="com.study.hibernate.domain.Order"/> </set> </class> </hibernate-mapping>
從表:dom
<hibernate-mapping> <class name="com.study.hibernate.domain.Order" table="tb_order" catalog="db_hibernate"> <id name="id" column="id" type="java.lang.Long"> <generator class="native"></generator> </id> <property name="addr" column="addr" type="java.lang.String"></property> <property name="totalprice" column="totalprice" type="java.lang.Long"></property> <many-to-one name="user" class="com.study.hibernate.domain.TbUser" column="tb_user_id" /> </class> </hibernate-mapping>
執行測試:報上面的錯誤eclipse
public void saveTest3(){ Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); TbUser user = new TbUser(); user.setName("wangwu"); user.setAge(new Long(12)); user.setCity("bj"); Order order = new Order(); order.setAddr("nihao"); order.setTotalprice(new Long(200)); order.setUser(user); session.save(order); transaction.commit(); session.close(); sessionFactory.close(); }
緣由是由於在沒有保存主表的狀況下保存了子表,解決辦法在<many-to-one> 中加入cascade測試
<many-to-one name="user" cascade="all" class="com.study.hibernate.domain.TbUser" column="tb_user_id" />
問題解決,輸出結果爲:ui
Hibernate: insert into db_hibernate.tb_user (name, age, city) values (?, ?, ?) Hibernate: insert into db_hibernate.tb_order (addr, totalprice, tb_user_id) values (?, ?, ?)