对象引用了一个未保存的瞬态实例:在刷新之前保存瞬态实例。

17

我有两个实体:PlayerProfileEntity和UserInfoEntity。我在userInfoEntity和PlaterProfileEntity上进行联接,并将记录保存在数据库中:

Session session = sessionFactory.openSession();
Transaction tr = session.beginTransaction();
Criteria crit = session.createCriteria(PlayerProfileEntity.class);
player.setUserId(new UserInfoEntity());
player.getUserId().setAddress(user.getUserId().getAddress());
session.save(player);
tr.commit();

我在我的PlayerProfileEntity类中使用了这个关联。

@ManyToOne (fetch = FetchType.LAZY)
@Cascade({CascadeType.REFRESH})
@JoinColumn(name="userid")

我收到了这个错误:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save     the transient instance before flushing: com.shared.entity.UserInfoEntity

注意:如果我使用CascadeType.All,会出现以下错误:

Cannot add or update a child row: a foreign key constraint fails

你有任何想法如何解决这个问题吗?

谢谢。

6个回答

21

TransientObjectException在你尝试保存对象但没有保存适当的关联时出现。你必须先保存UserInfoEntity,然后才能保存你的PlayerInfoEntity类。

player.setUserId(new UserInfoEntity());

使用此方法,您正在将特定的 UserInfoEntity 分配给 PlayerInfoEntity。但是 UserInfoEntity 没有任何 ID。这两者该如何映射?这就是为什么会出现异常的原因。

希望这能帮到您。


4
您应该使用CascadeType.PERSIST或CascadeType.ALL。

谢谢,但我已经在我的问题中提到了使用CascadeType.ALL,并且收到错误消息:无法添加或更新子行:外键约束失败,对此有什么想法吗? - user1226162
抱歉,我没有看到最后的注释。不过我认为我们应该集中精力解决你在CascadeType.ALL中遇到的错误。 - Marko Topolnik
你展示了一个涉及到Criteria的代码行,但它与你的代码无关。另一方面,缺少重要的代码来组装你要保存的Player。此外,这行代码让我感到困惑:player.getUserId().setAddress(user.getUserId().getAddress())。这是什么意思?而且为什么UserId是一个复合对象? - Marko Topolnik
1
如果user是一个持久化对象,那么他的address也是持久化的。你将该地址设置为非持久化对象player。这可能是你问题的原因。 - Marko Topolnik
谢谢,我想这可能是一个初学者的问题,但是玩家是一个非持久化对象,我该如何使玩家对象持久化?谢谢。 - user1226162
2
这是关于Hibernate感知到的对象当前状态的内容。当你执行session.save(o)时,它会在保存之前隐式地执行session.persist(o)。你也可以自己调用它。此时,Hibernate将“注意到”你的对象并将其注册到会话中。 - Marko Topolnik

1
public void savePlayerMethod(PlayerInfoEntity player){

if(player == null){
   player = new PlayerInfoEntity();
}
player.setUserId(getSavedUserInfo());
Session session = SessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(userInfo);
transaction.committ();
}

public UserInfoEntity getSavedUserInfo(){
UserInfoEntity userInfo = new UserInfoEntity();
Session session = SessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(userInfo);
transaction.committ();
}

0
我刚刚遇到了同样的错误,当尝试通过Session#save()方法存储一个未保存的对象并分配了ID时。我认为问题可能是您的未保存对象图已经被赋予了一个ID(这是save方法尝试执行的操作),这会在某种程度上干扰save方法的级联操作。尝试使用Session#persist()代替,级联应该可以正常工作,即使对象已经被分配了ID。

0
我也遇到了同样的问题,经过反复调试,我发现将实体类中的@AllArgsConstructor注解删除并添加...
@Tolerate
public <ClassName>() {
}

对我有用。


-1

嗯,

我遇到了类似的问题,我做的是

Object tmp = session.get(Object.class,ob.getId())
if(tmp!=null){
    session.evit(tmp); // or merge
}
session.saveOrUpdate(ob);

这对我有用。

它获取短暂对象并将其逐出或合并。

现在使用save或update方法保存您的新对象。


1
你需要更详细地解释这个解决方案。驱逐然后保存如何解决这个问题?通常,这个问题是由于没有保存附加到当前正在保存的实体而引起的。 - Randy Stegbauer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接