对象引用未保存的瞬态实例:如何刷新或返回保存的对象 [英] object references an unsaved transient instance: how to flush or return saved object

查看:221
本文介绍了对象引用未保存的瞬态实例:如何刷新或返回保存的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个简单的实体:

  @Entity 
public class Language {
@Id
@GeneratedValue
private long id;

@Column(nullable = false,length = 3,unique = true)
私有字符串代码;
}

我使用 @保存了该实体的一个实例使用 @Transactional 注释方法的服务注释类,该方法使用DAO来保存实体

  sessionFactory.getCurrentSession()保存(对象); 

之后,我使用保存 Language 用于创建 EntityX 的实体,它用于 ManyToOne 关系...

  lang = new Language(); 
// ...
languageService.saveLanguage(lang);
e = new EntityX();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

EntityX 定义为...

  @Entity 
public class EntityX {
@ManyToOne
@JoinColumn(nullable = false )
私人语言语言;
// ...
}

我总是得到异常 p>

 线程main中的异常org.hibernate.TransientObjectException:对象引用一个未保存的瞬态实例 - 在flush之前保存瞬态实例:somepackage。语言

我尝试在 EntityX 语言的关系,正如其他帖子中所建议的那样,但它不起作用。



如果我使用一些HQL查询重新加载已保存的 Language 实体,方法是使用一些HQL查询找到它,然后一切正常,但是它很远离'好'。



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



有没有人有任何想法如何解决它?

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



如果您的代码处于单个事务中,您尝试了保存实体以强制Hibernate存储 Language 到数据库并为其分配一个有效的之前保存 flush() > @Id entifier?



毕竟 - 恕我直言 - 如果您有来自实体和语言的依赖关系,最好的选择是:

  @ManyToOne(cascade = CascadeType.ALL)
private语言语言;

并将您的代码更改为:

  e = new EntityX(); 
语言lang = new Language();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

并且您不需要在两个步骤(语言+实体)中坚持实体;管理语言+实体作为单个项目



PS :org.hibernate.Session的save(...)方法不返回保存的对象,因为对象保持不变(引用不变),只是对象属性发生变化(例如标记为 @Id 的那个) / p>

编辑:

使对象持久化(session.save(),我的意思是)不会立即插入/更新;没有级联提示Hibernate的外观没有检测到EntityX和Language之间的依赖关系,并且在保存EntityX之前没有执行一个语言的sql插入。
languageService.save(语言)调用不执行session.flush (),因为你处于相同的 @Transactional 并且没有session.commit()。没有执行session.flush(),最好的选择是Language对象仍然被标记为transient。

你可以做一个检查:提取服务保存代码(language entityX),并把所有内容放在单独的 @Transactional 中,并检查Hibernate是否仍然给你错误


我最好的选择是在中间执行一个flush()或者改变你的映射,没有其他办法。

I use Spring 3.2.3 and Hibernate 4.2.3 and JDK 7.

I have a simple entity:

@Entity
public class Language {
    @Id
    @GeneratedValue
    private long id;

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

I saved an instance of this entity using a @Service annotated class with a @Transactional annotated method which uses a DAO which saves the entity with

sessionFactory.getCurrentSession().save(object);

After that I used the saved Language entity for creating EntityX, which used it in an ManyToOne relation ...

lang=new Language();
// ...
languageService.saveLanguage(lang);
e=new EntityX();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

and EntityX is defined as ...

@Entity
public class EntityX {
    @ManyToOne
    @JoinColumn(nullable = false)
    private Language language;
        // ...
}

I always get the exception

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language

I try to use some cascade-definitions in EntityX's relation to Language as suggested in other posts, but it has no effect.

If I reload the saved Language entity by finding it by its code using some HQL-query, then everything works fine, but that it is far away from being 'nice'.

Unfortunately the save(...) method(s) of org.hibernate.Session does not return the saved object.

Has anybody any ideas how to solve it?

解决方案

Is you code in a single @Transactional method?
If not the problem can be that, after any call to service method, transaction will be commit and session cleared. When you try to save entity, language object is not detected in session and managed as transient instance and give the error.

In case your code is under single transaction did you try a flush() before saving entity to force Hibernate store Language to database and assign it a valid @Identifier?

After all - IMHO - if you have a dependency from Entity and Language the best choice is:

@ManyToOne(cascade = CascadeType.ALL)
private Language language;

and change your code as:

e=new EntityX();
Language lang = new Language();
// ...
e.setLanguage(lang);
otherService.saveEntity(e);

and you don't need to persist entity in two steps (language + entity); manage language+entity as single item

PS: The save(...) method(s) of org.hibernate.Session does not return the saved object because the object will remain the same (reference doesn't change), just object properties changes (like the one marked this @Id, for example)!

EDIT:
Make an object persistent (session.save() it I mean) don't result in a immediate insert/update; without cascade hint Hibernate look doesn't detect dependency between EntityX and Language and doesn't perform a sql insert of Language before saving EntityX.
languageService.save(language) call doesn't perform session.flush() because you are under same @Transactional and without session.commit() no session.flush() is performed and best option is that Language object is still marked as transient.
You can do a check: extract services save code (language entityX) and put all in single @Transactional and check if Hibernate still give you error.
My best option is still perform a flush() in the middle or change your mapping, no other way

这篇关于对象引用未保存的瞬态实例:如何刷新或返回保存的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆