http://stackoverflow.com/questions/24721688/org-hibernate-persistentobjectexception-detached-entity-passed-to-persist-whe
http://myjourneyonjava.blogspot.com/2013/12/difference-between-opensession-and.html
http://stackoverflow.com/questions/9954590/hibernate-error-querysyntaxexception-users-is-not-mapped-from-users
http://blog.jhades.org/how-does-spring-transactional-really-work/
org.hibernate.PersistentObjectException: detached entity passed to persist
This error can be explained like this (ouf, how do I do this without describing the entire object lifecycle of Hibernate/JPA..?):
With JPA/Hibernate you define classes to be
Entity
s. What this means is that objects of this class can be managed by Hibernate, and thus be stored in the database.@Entity
public class Entity { /** ... */ }
When you create a new object of a class that is an
Entity
(new Entity()
), Hibernate knows nothing about it. It is not stored in the database, and is not under the control of Hibernate in any way. If we want these things to happen, we need to persist
our object (em.persist(entity)
). When we do this, the object state is stored in the database, but also, the object itself becomes managed by Hibernate, which means that Hibernate will keep track of the object's state. In addition, if you have assigned Hibernate to generate id's, the object will be assigned an id.
When you load an object from the database through Hibernate, this object will also be managed by Hibernate. A newly persisted, or a loaded object will both have an id, and will both be managed by Hibernate. But, the connection between the object and Hibernate can be broken! When this happens, the object becomes
detached
. A detached
object is really just an object of an entity
class, that has its id set, but is not managed by Hibernate.
The options we have when it comes to a
This will merge the state of the detached object with the database state corresponding to the objects id.
detached
object are different from the ones we have with a managed object, or a new object. Unlike managed objects, detached
objects are not allowed to be passed to the persist
-method, since they already have an id, which means that they must have been persisted already! When one wants to take a detached
object and make it managed, the merge
-method is the one to use. (http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#merge(T) )This will merge the state of the detached object with the database state corresponding to the objects id.
Calling
merge
with a new object (without id) will assign an id to it and save it, but beware that it will not do anything with the object pass as a parameter, rather it will return the managed object.public Entity saveDetached(final Entity entity) {
return em.merge(entity);
}
In your case, the solution will depend on a few factors, but if the referred
Pagina
will always be one already existing in the database I would just remove the cascading of the persist
operation from it, and keep using em.persist()
(merge
has its weaknesses..) If it might be new sometimes you would additionally need to add some logic to figure out whether or not to persist it (before persisting the owning object). (I also think it might work to load the Pagina
and Produto
from the database and assigning them to the new Pagina
before persist
.)
TL;DR
When reintroducing a
detached
object to the persistence-context, use the merge
-method of the EntityManager
, and not the persist
-method.http://myjourneyonjava.blogspot.com/2013/12/difference-between-opensession-and.html
Session openSession() throws HibernateException
It will return a new session object on every call, which is actually a instance oforg.hibernate.impl.SessionImpl.
- We can use this method when we decided to manage the Session our self.
- It does not try to store or pull the session from the current context.
- If we use this method, we need to flush() and close() the session. It does not flush and close() automatically.
Transaction transaction = null; Session session = HibernateUtil.getSessionFactory().openSession(); try { transaction = session.beginTransaction(); // do Some work session.flush(); // extra work transaction.commit(); } catch(Exception ex) { if(transaction != null) { transaction.rollback(); } ex.printStackTrace(); } finally { if(session != null) { session.close(); // extra work } }
Session getCurrentSession() throws HibernateException
Obtains the current session. The "current session" refers to a Hibernate Session bound by Hibernate behind the scenes, to the transaction scope.
A session is opened whenever getCurrentSession() is called for the first time and closed when the transaction ends. This creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.
We can use getCurrentSession() method when our transaction runs long time. To use this method we need to configure one property in hibernate.cfg.xml file
https://www.mkyong.com/hibernate/hibernate-transaction-handle-example/try{
session = HibernateUtil.getSessionFactory().openSession();
tx = session.beginTransaction();
tx.setTimeout(5);
//doSomething(session);
tx.commit();
}catch(RuntimeException e){
try{
tx.rollback();
}catch(RuntimeException rbe){
log.error("Couldn’t roll back transaction", rbe);
}
throw e;
}finally{
if(session!=null){
session.close();
}
}
Hibernate error - QuerySyntaxException: users is not mapped [from users]http://stackoverflow.com/questions/9954590/hibernate-error-querysyntaxexception-users-is-not-mapped-from-users
In the HQL , you should use the java class name and property name of the mapped
@Entity
instead of the actual table name and column name , so the HQL should be :List<User> result = (List<User>) session.createQuery("from User").list();
http://blog.jhades.org/how-does-spring-transactional-really-work/
@Configuration
public
class
EntityManagerFactoriesConfiguration {
@Autowired
private
DataSource dataSource;
@Bean
(name =
"entityManagerFactory"
)
public
LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf = ...
emf.setDataSource(dataSource);
emf.setPackagesToScan(
new
String[] {
"your.package"
});
emf.setJpaVendorAdapter(
new
HibernateJpaVendorAdapter());
return
emf;
}
}