User u = new User(); s.save(u);// Order order = new Order(u); s.save(order); tx.commit();
那cascade="save-update"是干嘛用的?
晕~~~在many-to-one 使用级联应该没有意义的 请参考hibernate 3.1x DOC 第11章: It doesn't usually make sense to enable cascade on a <many-to-one> or <many-to-many> association. Cascade is often useful for <one-to-one> and <one-to-many> associations.
It doesn't usually != It never
many-to-one 是不会保存主键对象的,因为他是外键约束,他会认为主键的对象已经存在于数据库中了 不信你可以先创建一个只有主键值,其他值为null的USER对象,然后order.set(user) save order 你看数据库数据,会发现保存成功所以你必须先user.add(order) 然后再save user 这样就可以全部保存 one-to-many就不一样了
当然,不实用的东西我是不会用的,我这不是在尝试吗?要把所有的情况下的表现都研究透彻才行。另外我发现,在多对多关系中,如果连接关系采用一个类来表示,也就是拆成两个以多对关系的时候,我可以在many-to-one中设置cascade="save-update"。这时候我认为就很有意义了。比如Student,Course是多对多的,连接类是Mark。 Student s = new Student(); Course c = new Course();Mark m = new Mark(s,c); session.save(m); 这样我只要保存关联就可以了。在我可控的知识范围内,我保证了语句的最少化,而且增加了可读性,这有什么不好呢?否则我就必须这样写 Student student = new Student(); Course course = new Course();
我市修改了mypetstore for mysql的。 把原来的hibernate2 升级到了3.0 和sqlserver2000
10:50:06,129 DEBUG OrderBean:28 - Creating order bean 10:50:06,129 DEBUG OrderBean:46 - Order bean is created 10:50:06,139 DEBUG OrderBean:36 - service locator is set 10:50:06,139 DEBUG OrderBean:55 - createOrderAction is invoked Hibernate: select sequence0_.NAME as NAME10_0_, sequence0_.SEQNUM as SEQNUM10_0_ from SEQUENCE sequence0_ where sequence0_.NAME=? 10:50:06,169 DEBUG OrderDaoHibernateImpl:23 - 1002 mypetstore.model.businessobject.Order@1649a55 Hibernate: insert into ORDERS (USERID, ORDERDATE, SHIPADDR1, SHIPADDR2, SHIPCITY, SHIPSTATE, SHIPZIP, SHIPCOUNTRY, BILLADDR1, BILLADDR2, BILLCITY, BILLSTATE, BILLZIP, BILLCOUNTRY, COURIER, TOTALPRICE, BILLTOFIRSTNAME, BILLTOLASTNAME, SHIPTOFIRSTNAME, SHIPTOLASTNAME, CREDITCARD, EXPRDATE, LOCALE, ORDERID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) Hibernate: update SEQUENCE set SEQNUM=? where NAME=? Hibernate: update LINEITEM set ORDERID=? where ORDERID=? and LINENUM=? 10:50:06,209 ERROR AbstractFlushingEventListener:299 - Could not synchronize database state with session org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: mypetstore.model.businessobject.LineItem at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:216) at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108) at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:71) at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:697) at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1037) at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:26) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:227) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:490) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:495) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:468) at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:258) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174) at $Proxy13.saveOrder(Unknown Source) at mypetstore.view.bean.OrderBean.createOrderAction(OrderBean.java:57)
tx = s.beginTransaction();
User u = new User();
s.save(u);//
Order order = new Order(u);
s.save(order);
tx.commit();
It doesn't usually make sense to enable cascade on a <many-to-one> or <many-to-many> association. Cascade is often useful for <one-to-one> and <one-to-many> associations.
不信你可以先创建一个只有主键值,其他值为null的USER对象,然后order.set(user)
save order
你看数据库数据,会发现保存成功所以你必须先user.add(order)
然后再save user
这样就可以全部保存
one-to-many就不一样了
楼上的理解有不对的地方,早点纠正吧。你可以多找一些基础的资料看一下,而且以后没弄清楚可别乱说哦,以免误导了新手。
对于many-to-one是可以级联的,我已经试验成功了,如果不起作用为什么还保留这个级联属性呢,设计师不可能犯这种错误吧。而且《精通hibernate》中也有非常明确的例子,但是他没有强调主键应该用包装类型,所以导致我的出现了问题。
Student s = new Student();
Course c = new Course();Mark m = new Mark(s,c);
session.save(m);
这样我只要保存关联就可以了。在我可控的知识范围内,我保证了语句的最少化,而且增加了可读性,这有什么不好呢?否则我就必须这样写
Student student = new Student();
Course course = new Course();
Mark m = new Mark(student,course);
student.getMarks().add(m);//会造成student加载所有的
course.getMarks().add(m);//会造成course加载所有的
s.save(student);
s.save(course);
tomcat5 + sqlserver2000 + hibernate3.1 + spring
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="mypetstore.model.businessobject">
<class name="Order" table="ORDERS">
<id name="orderId" column="ORDERID" unsaved-value="null">
<generator class="assigned"/>
</id> <property name="username"
column="USERID"
not-null="true"/> <property name="orderDate"
column="ORDERDATE"
type="date"
not-null="true"/> <property name="shipAddress1"
column="SHIPADDR1"
not-null="true"/> <property name="shipAddress2"
column="SHIPADDR2"/> <property name="shipCity"
column="SHIPCITY"
not-null="true"/> <property name="shipState"
column="SHIPSTATE"
not-null="true"/> <property name="shipZip"
column="SHIPZIP"
not-null="true"/> <property name="shipCountry"
column="SHIPCOUNTRY"
not-null="true"/> <property name="billAddress1"
column="BILLADDR1"
not-null="true"/> <property name="billAddress2"
column="BILLADDR2"/> <property name="billCity"
column="BILLCITY"
not-null="true"/> <property name="billState"
column="BILLSTATE"
not-null="true"/> <property name="billZip"
column="BILLZIP"
not-null="true"/> <property name="billCountry"
column="BILLCOUNTRY"
not-null="true"/> <property name="courier"
column="COURIER"
not-null="true"/> <property name="totalPrice"
column="TOTALPRICE"
not-null="true"/> <property name="billToFirstName"
column="BILLTOFIRSTNAME"
not-null="true"/> <property name="billToLastName"
column="BILLTOLASTNAME"
not-null="true"/> <property name="shipToFirstName"
column="SHIPTOFIRSTNAME"
not-null="true"/> <property name="shipToLastName"
column="SHIPTOLASTNAME"
not-null="true"/> <property name="creditCard"
column="CREDITCARD"
not-null="true"/> <property name="expiryDate"
column="EXPRDATE"
not-null="true"/> <property name="locale"
column="LOCALE"
not-null="true"/> <set name="lineItems" cascade="delete">
<key column="ORDERID"/>
<one-to-many class="LineItem"/>
</set>
</class>
</hibernate-mapping>
把原来的hibernate2 升级到了3.0 和sqlserver2000
10:50:06,129 DEBUG OrderBean:46 - Order bean is created
10:50:06,139 DEBUG OrderBean:36 - service locator is set
10:50:06,139 DEBUG OrderBean:55 - createOrderAction is invoked
Hibernate: select sequence0_.NAME as NAME10_0_, sequence0_.SEQNUM as SEQNUM10_0_ from SEQUENCE sequence0_ where sequence0_.NAME=?
10:50:06,169 DEBUG OrderDaoHibernateImpl:23 - 1002 mypetstore.model.businessobject.Order@1649a55
Hibernate: insert into ORDERS (USERID, ORDERDATE, SHIPADDR1, SHIPADDR2, SHIPCITY, SHIPSTATE, SHIPZIP, SHIPCOUNTRY, BILLADDR1, BILLADDR2, BILLCITY, BILLSTATE, BILLZIP, BILLCOUNTRY, COURIER, TOTALPRICE, BILLTOFIRSTNAME, BILLTOLASTNAME, SHIPTOFIRSTNAME, SHIPTOLASTNAME, CREDITCARD, EXPRDATE, LOCALE, ORDERID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update SEQUENCE set SEQNUM=? where NAME=?
Hibernate: update LINEITEM set ORDERID=? where ORDERID=? and LINENUM=?
10:50:06,209 ERROR AbstractFlushingEventListener:299 - Could not synchronize database state with session
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: mypetstore.model.businessobject.LineItem
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:216)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:71)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:697)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1037)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:26)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:227)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:490)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:495)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:468)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:258)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
at $Proxy13.saveOrder(Unknown Source)
at mypetstore.view.bean.OrderBean.createOrderAction(OrderBean.java:57)