首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象引用未保存的瞬态实例:如何刷新或返回保存的对象。

对象引用未保存的瞬态实例:如何刷新或返回保存的对象。
EN

Stack Overflow用户
提问于 2013-08-17 20:43:35
回答 2查看 20.1K关注 0票数 6

我使用Spring3.2.3和Hibernate 4.2.3以及JDK 7。

我有一个简单的实体:

代码语言:javascript
复制
@Entity
public class Language {
    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false, length = 3, unique = true)
    private String code;
}

我使用一个@Service注释类保存了这个实体的一个实例,并使用了一个@Transactional注释方法,该方法使用DAO将实体保存在

代码语言:javascript
复制
sessionFactory.getCurrentSession().save(object);

之后,我使用保存的 Language实体来创建EntityX,该实体在ManyToOne关系中使用.

代码语言:javascript
复制
lang=new Language();
// ...
languageService.saveLanguage(lang);
e=new EntityX();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

EntityX被定义为..。

代码语言:javascript
复制
@Entity
public class EntityX {
    @ManyToOne
    @JoinColumn(nullable = false)
    private Language language;
        // ...
}

我总是得到例外

代码语言:javascript
复制
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language

我试着在EntityXLanguage的关系中使用其他帖子中的一些级联定义,但没有效果。

如果我使用一些HQL查询通过Language实体的code找到保存的code实体,那么一切都很好,但它离‘好’还差得很远。

不幸的是,save(...)方法的org.hibernate.Session没有返回保存的对象。

有谁知道怎么解决这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-18 16:09:07

您是在单个@Transactional方法中编码吗?

如果不是,问题可能是,在调用服务方法之后,事务将被提交并清除会话。当您试图保存实体时,不会在会话中检测到语言对象,并将其作为临时实例进行管理,并给出错误。

如果您的代码位于单个事务下,那么在保存实体之前是否尝试过一个flush(),以强制Hibernate存储Language到数据库,并为其分配一个有效的@Id实体?

毕竟- IMHO -如果您有实体和语言的依赖,最好的选择是:

代码语言:javascript
复制
@ManyToOne(cascade = CascadeType.ALL)
private Language language;

并将代码更改为:

代码语言:javascript
复制
e=new EntityX();
Language lang = new Language();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

并且您不需要在两个步骤(语言+实体)中持久化实体;将language+entity管理为单个项

:保存(.)org.hibernate.Session的方法不返回保存的对象,因为对象将保持不变(引用不会更改),只会更改对象属性(例如,标记此@Id的对象)!

编辑:

使对象持久(我的意思是session.save())不会导致立即插入/更新;没有级联提示,Hibernate外观不会检测到EntityX和语言之间的依赖,并且在保存EntityX之前不会执行EntityX插入。

languageService.save( Language )调用不执行session.flush(),因为您在同一个@Transactional下,没有session.commit(),没有执行session.flush(),最好的选择是语言对象仍然标记为瞬态。

您可以进行检查:提取服务、保存代码(语言为entityX),并将其全部放在单个@Transactional中,并检查Hibernate是否仍然给您带来错误。

我最好的选择仍然是在中间执行刷新()或更改映射,没有其他方法。

票数 5
EN

Stack Overflow用户

发布于 2013-08-17 22:25:22

首先,如果code字段是主键(或者至少将其用作Hibernate的主ID ),请指定@Id:

代码语言:javascript
复制
@Id 
@GeneratedValue(generator="assigned")
@Column(length = 3)
private String code;

如果不指定ID列,可能会使Hibernate有点混乱;不过,请不要引用我的话。

如果save()在此之后仍然不能工作,则可以使用merge()

代码语言:javascript
复制
Language lang = new Language("XYZ");
lang = session.merge(lange);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18293169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档