I have this class which is dedicated to persist data in db through persistance layer of hibernate.
public class TLinkEquipementDAOImpl implements TLinkEquipementDAO {
private static final Log log = LogFactory
.getLog(TLinkEquipementDAOImpl.class);
@PersistenceContext
private EntityManagerFactory emf = PersistenceManager.getInstance()
.getEntityManagerFactory();
private EntityManager entityManager = emf.createEntityManager();
private EntityTransaction tx = entityManager.getTransaction();
public void persist(TLinkEquipement transientInstance) {
log.debug("persisting TLinkEquipement instance");
try {
tx.begin();
entityManager.persist(transientInstance);
tx.commit();
log.debug("persist successful");
} catch (RuntimeException re) {
tx.rollback();
log.error("persist failed", re);
throw re;
}
}
//Staff
}
The problem is that it does not persist data.
The stack is:
Exception in thread "main" java.lang.IllegalStateException: Transaction not active
at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:82)
at sau.se.domain.dao.Impl.TLinkEquipementDAOImpl.persist(TLinkEquipementDAOImpl.java:47)
at sau.se.domain.service.Impl.TLinkEquipementServiceImpl.persist(TLinkEquipementServiceImpl.java:29)
at sau.se.extractor.InfoExtract.getAllSPData(InfoExtract.java:346)
at sau.se.extractor.InfoExtract.main(InfoExtract.java:436)
But i have to note, that it works fine in other classes.
UPDATE:
when i make print of tx.isActive()
it gives me false
.
UPDATE
I tried to more get some info about the error:
I got where the problem is:
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: sau.se.domain.model.TLinkEquipement.TEquipementsByIdEquipement2 -> sau.se.domain.model.TEquipements
at org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:376)
in fact, the table TLinkEquipement
has 2 fk to the same table TEquipements
, and me, i persist data of TEquipements
then those of TLinkEquipement
Probably tx.begin()
threw an exception. That means that in the catch
clause there was no active transaction to rollback. That's why tx.rollback()
threw another exception (shadowing the original error).
To see the source exception rewrite your catch
block:
} catch (RuntimeException re) {
log.error("persist failed", re); //moved to top
tx.rollback();
throw re;
}
Also not that you're mixing concepts here. On one hand you're declaring injected entity manager (@PersistenceContext
), on the other hand you're creating using EntityManagerFactory
programmatically.
If this is a JEE bean, it should look like this:
@Stateless
public class TLinkEquipementDAOImpl implements TLinkEquipementDAO {
private static final Log log = LogFactory.getLog(TLinkEquipementDAOImpl.class);
@PersistenceContext
private EntityManager entityManager;
public void persist(TLinkEquipement transientInstance) {
log.debug("persisting TLinkEquipement instance");
entityManager.persist(transientInstance);
log.debug("persist successful");
}
//Staff
}
Here transaction management and entity manager management is handled by the container (application server).
If this class is used outside of a container then I could look like this:
public class TLinkEquipementDAOImpl implements TLinkEquipementDAO {
private static final Log log = LogFactory.getLog(TLinkEquipementDAOImpl.class);
//I'm assuming getEntityManagerFactory() returnes an already created EMF
private EntityManagerFactory emf = PersistenceManager.getInstance()
.getEntityManagerFactory();
private EntityManager entityManager = emf.createEntityManager();
public void persist(TLinkEquipement transientInstance) {
EntityTransaction tx = entityManager.getTransaction();
log.debug("persisting TLinkEquipement instance");
try {
tx.begin();
entityManager.persist(transientInstance);
tx.commit();
log.debug("persist successful");
} catch (RuntimeException re) {
log.error("persist failed", re);
if(tx.isActive()) {
tx.rollback();
}
throw re;
}
}
//Staff
}
For others who may get this error messsage: "Exception in thread "main" java.lang.IllegalStateException: Transaction not active"
Check your merge operation. You may be trying to merge an object that is supposed to be a reference instead of an object you just created. By reference, I mean... you need to have a live reference to that object from the database... hence the "transaction not active" error message.
Here is an example piece of code for querying an object from the database with JPQL:
public static Users getUserByName(EntityManager em, String name) throws NoResultException, Exception {
Users user = null;
user = em.createQuery("SELECT u from Users u WHERE u.name =:name", Users.class).setParameter("name", name).setMaxResults(1).getSingleResult();
return user;
}
I just came across this problem, and now I had solved it. But I realize that I was so stupid.
the reason I find is that the data I want to commit has a foreign key but I forget that, so the transaction will always close itself. I add the foreign key in the database, and then the test or main method run successfully.
the Key point I want to say is that please write this in your code.
} catch (Exception ex) {
ex.printStackTrace();
tx.rollback();}
and you will easily find the reason why the transaction closed or not alive. that is my experience,hope useful!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With