org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.anbo.po.Commodity
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:101)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:777)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1165)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.anbo.test.test.add(test.java:47)
at com.anbo.test.test.main(test.java:61)
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.anbo.po.Commodity
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:101)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:777)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1165)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.anbo.test.test.add(test.java:47)
at com.anbo.test.test.main(test.java:61)
出现该错误的原因是没有使用级联操作,但是保存的对象却有关联关系。
如:
public class Commodity {
private Integer id; //商品编号
private String commodityName; //商品名称
private String manufacturer; //生产厂家
private String commodityDepict; //商品描述
private Double commodityPrice; //商品价格
private Double fcPrice; //帆成网价格
private Integer commodityAmount; //商品总数量
private Integer commodityLeaveNum; //商品剩余数量
private Timestamp regTime; //商品上架时间
private byte[] image; //商品图片
.......
}
public class CommodityClass implements java.io.Serializable{
private Integer id; //商品种类编号
private String commodityClassName; //商品种类名称
private Set<Commodity> commodities =new HashSet<Commodity>();
public CommodityClass() {
super();
}
.....
}
上述的Commodity类和CommodityClass类之间存在一对多的关系。
如果在映射文件中设置了级联,那么控制台会打印出如下语句:
Hibernate:
select
max(id)
from
commodityClass
Hibernate:
select
max(id)
from
commodity
Hibernate:
insert
into
commodityClass
(commodityClassName, id)
values
(?, ?)
Hibernate:
insert
into
commodity
(commodityName, manufacturer, commodityDepict, commodityPrice, fcPrice, commodityAmount, commodityLeaveNum, regTime, image, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
update
commodity
set
commodityClass=?
where
id=?
可是如果在映射文件中没有设置级联关系。
而保存的时候只保存了CommodityClass对象,虽所CommodityClass对象能被插入数据库中,但还是会报上面贴的错误。
如果设置级联只保存了ComodityClass的对象,那么数据插入到数据库中,该记录中的commodityClass这一个字段却为空。
由此我们可知这两个对象保存的先后顺序。
设置级联 保存CommodityClass 不设置级联 保存 CommodityClass 和保存Commodity
两个的保存顺序是 先保存Commodity表中的数据 然后在保存CommodityClass表中的数据 ,然后根据CommodityClass表中的id去更新 Commodity表中的commodityClass字段。
如果在没有设置级联下只保存CommodityClass对象,那么控制台就会报上述错误以及打印如下语句。
Hibernate:
select
max(id)
from
commodityClass
Hibernate:
insert
into
commodityClass
(commodityClassName, id)
values
(?, ?)
Hibernate:
update
commodity
set
commodityClass=?
where
id=?
这是控制台打印的语句,如果连这条记录都没有,那么怎么插入这个id?
错误解决方案:
1. 设置级联
2. 不设置级联,那么就保存两个对象。
如:
session.save(commodity);
session.save(commodityClass);