An object refers to an unsaved transient instance: how to clear or return a saved object

I am using Spring 3.2.3 and Hibernate 4.2.3 and JDK 7.

I have a simple object:

@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 object using the annotated @Service class with the annotated @Transactional method, which uses a DAO that saves the object with

 sessionFactory.getCurrentSession().save(object); 

After that, I used the saved Language object to create EntityX , which used it with respect to ManyToOne ...

 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 an exception

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

I am trying to use some cascading definitions regarding EntityX to Language , as suggested in other posts, but this has no effect.

If I reload the saved Language object, finding it with code using some HQL query, everything works fine, but that it is far from being “good”.

Unfortunately, the save(...) org.hibernate.Session does not return the saved object.

Does anyone have any ideas how to solve it?

+6
source share
2 answers

Are you code in one @Transactional method?
If not a problem, it may be that after any call to the service method, the transaction will be committed and the session will be cleared. When you try to save an object, the language object is not detected in the session and is managed as a temporary instance and gives an error.

If your code is under one transaction, did you try flush() before saving the object to force storage of the Hibernate Language repository in the database and assign it a valid @Id entifier?

After all - IMHO - if you have a dependency on 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 do not need to save the object in two stages (language + entity); manage language + object as a single element

PS : the save method () (...) of the org.hibernate.Session method does not return the saved object, because the object will remain the same (the link does not change), just changing the properties of the object (for example, marked with this @Id )!

EDIT:
Making an object persistent (session.save () I mean) does not immediately insert / update; without a cascading hint. Hibernation does not detect a dependency between EntityX and the language and does not insert the sql language before saving EntityX.
languageService.save (language) the call does not execute session.flush () because you are under the same @Transactional and without session.commit () no session.flush () is executed, and the best option is that the Language object still marked as transitory.
You can check: extract the services, save the code (language entityX) and put everything in a single @Transactional and check if Hibernate allows you to get an error.
My best option is still doing flash () in the middle or changing your mapping, there is no other way

+5
source

First, if the code field is the primary key (or at least you use it as the primary identifier for sleep mode), specify @Id:

 @Id @GeneratedValue(generator="assigned") @Column(length = 3) private String code; 

Without specifying an identifier column, you can slightly hibernate; although I do not quote me about this.

If after that save() still does not work, you can use merge() :

 Language lang = new Language("XYZ"); lang = session.merge(lange); 
+2
source

Source: https://habr.com/ru/post/951938/


All Articles