A collection needs to be fetched lazily. If I then try to access its components, I get the following Exception :
failed to lazily initialize a collection of role:
mapp3.model.ProductDefinition, could not initialize proxy - no Session
So I retrieved the session from the entityManager this way:
Session session = entityManager.unwrap(Session.class);
but this causes the following exception :
Error executing command: Transaction management is not available for container managed EntityManagers.
I am using Hibernate inside a Karaf container. How else could I proceed to either be able to browse the lazily fetched collection, either to start a Session with a container managed EntityMananger ?
Looks like you're using the entity outside of EM context. eg. if it used in some jsp etc.
Please invoke getter method for the collection right before you're sending it out of EM context.
Related
I implemented the two session factories in my spring hibernate project.
why is it happening, when i use the first session factory for load() it works fine but when i use second session factory for load method it returns the org.hibernate.LazyInitializationException: could not initialize proxy - no session error.
Finally, I got the solution of the above problem. you need to create open session in view for second session factory also and to create the open session in view for second session factory.In web.xml configuration of open session in view for both session factories is required.
I was trying to figure out how hibernate works and few things are there I want to how they works and I wanted to know if I understood correctly.
EntityManagerFactory emf = Persistence.createEntityManagerFactory();
The above does following things
Creates entitymanager factory instance.
EntityManagerFactory stores the mapping for all the entity classes.
Its the provider of entity manager instances.
what else above line does?
EntityManager em = emf.createEntityManager()
createa an entitymanager.
EntityManager is responsible for managing lifecycle of managed objects.
what else above line do? does it create a session with database?
em.getTransaction().begin();
Does above lines creates a database session?
is session and transaction and session are java side things or database side things?
what transaction and session means ?
em.getTransaction().commit();
I feel that this line does all the work of creating transaction and saving the data to the database. am I correct?
em.close();
this line closes the database session.
emf.close();
all the mapping present in the factory are lost and eligible for GC?
Am I correct with my understandings?
I used jboss, and hibernate 4 within jpa (JTA transaction type). In a DAOUtil class, I try to get entity manager, I can get it and do a query. But when I flush entity manager, the error happened.
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:970)
at com.vms.dao.hibernate.HibernateDAOSession.flush(HibernateDAOSession.java:288)
I searched on internet, and they say: if we use jpa with jta transaction type, we must inject EntityManager into a ejb, is this correct?
If this is correct, I've a concern: how about threadpool for entity manager? I confused alot of thing about that.
Please anyone give my the true way, to use jpa within JTA transaction type.
Added.
I think this issue because I've a getter to get EntityManager outside EJB.
One more question, in JPA with JTA transaction type, I think we could not update by native sql. IN ejb I've below code.
public int executeNativeUpdate(String query, Map<String, Object> params) {
Query q = em.createNativeQuery(query);
setParameters(q, params);
return q.executeUpdate();
}
Error raised when running into code:
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
Anyone can explain. I'm beginer in JPA adn JTA. If I use JPA with JTA transaction type and inject the EntityManager into Stateless EJB, EJB container will handle transaction for me, right? I no need do begin/commit a transaction. How about native sql? Can EJB container handle all?
If you use JTA transactional type then container manage transactions (application server, or openjpa, or other). In this case you should use EJB, where every method call is wraped in transaction. Create, commit, rollback, manage entity manager - work of container.
As I understand when I use hibernate with Spring transactions, a session is bound to thread using ThreadLocal. My questions are:
How can I access the session or session factory (without injecting it to the bean) (thus by thread locale)?
2.How can I do the same in terms of JPA, thus using EnityManager / EntityManagerFactory?
You should use the SessionFactory.getCurrentSession() to get your Session. What the session returned from this method depends on the configuration parameter hibernate.current_session_context_class in the hibernate.cfg.xml . If it is set to thread , the returned session is get from the ThreadLocal , which means that if it is called for the first time in the current Java thread, a new Session is opened and returned . If it is called again in the same thread , the same session will be returned.
AFAIK , there are no equivalent SessionFactory.getCurrentSession() in JPA . I think you have manually set and get the EntityManager to the ThreadLocal
Reference
Hibernate Contextual sessions
Sessions and transactions
I was trying to figure this out today and ended up doing it this way:
#PersistenceContext(unitName = "jpaSessionFactoryName")
private EntityManager jpaSession;
I found this documentation very helpful:
https://docs.spring.io/spring/docs/4.3.2.RELEASE/spring-framework-reference/htmlsingle/#orm-jpa-straight
When you use #PersistenceContext, Spring injects a proxy that gives you an EntityManager bound to the current transaction (or a new one, if there is not any). This looks like a direct substitute for hibernate's:
sessionFactory.getCurrentSession();
which is exactly what I was looking for.
In the standalone application(single threaded command line tool) I am developing ,I use Spring +Hibernate.
It has DAO and Service layers and for DAOs I use HibernateDAOSupport.
The collections in domain model are lazy-loading.
Since for lazy-loading I need to keep the Session opended,I open session at start of my application using:
HibernateTemplate tmpl;
SessionFactoryUtils.initDeferredClose(tmpl.getSessionFactory());
//do file reads,parse CSV , persist objects (normally takes along time)
//
//Finally
SessionFactoryUtils.processDeferredClose(tmpl.getSessionFactory());
But during execution ,I get the error:
Exception in thread "main"
org.springframework.orm.hibernate3.HibernateSystemException:
Illegal attempt to associate a
collection with two open sessions;
nested exception is
org.hibernate.HibernateException:
Illegal attempt to associate a
collection with two open sessions
Caused by:
org.hibernate.HibernateException:
Illegal attempt to associate a
collection with two open sessions at
org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
at
org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
at
org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at
org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at
org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at
org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
at
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
at
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at
org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33)
at
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at
org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:564)
at
org.hibernate.impl.SessionImpl.update(SessionImpl.java:552)
How to fix this?
at
org.hibernate.impl.SessionImpl.update(SessionImpl.java:544)
at
org.springframework.orm.hibernate3.HibernateTemplate$14.doInHibernate(HibernateTemplate.java:657)
at
org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
at
org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:654)
at
org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:650)
at
com.bigg.nihonbare.common.dao.hibernate.CommonDAOImpl.updateFamily(CommonDAOImpl.java:40)
at
com.bigg.nihonbare.common.service.impl.CommonServiceImpl.updateFamily(CommonServiceImpl.java:55)
at
com.bigg.nihonbare.util.flow.DynaRowHibernateUpdateHandler.handleRow(DynaRowHibernateUpdateHandler.java:72)
NOTE : In my DAOs I only have used methods like;
return (Long) this.getHibernateTemplate().save(family);
return (Family) this.getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session
.createCriteria(Family.class);
criteria.add(Expression.eq("familyId", familyId));
if (criteria.list().size() > 0) {
return criteria.list().get(0);
}
return null;
}
});
Watch for getHibernateTemplate().getSessionFactory().openSession() in your DAO, you might be ending up opening 2 sessions, since you lately switched to this architecture, I know it from your other previous question.
Hint: Use getSession() instead. This SpringSource Forum's thread might be helpful.
There are a lot of session associated to each thread separately .session is not a
Shared variables but sessionfactory is,session is created by spring container if you inject sessionfactory into DAO.