I am getting an error after removing object from database.
Error is:
java.lang.IllegalStateException: Transaction not active
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:70)
I have simple app. I have EntityManagerFactory created on start up.
Every time if I want to work with database I create EntityManager and after work I close it like this:
Start up:
EntityManagerFactory emf = ....;
.
.
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.persist(OBJECT TO SAVE); //REALLY NEW OBJECT
} catch (Exception e) {
em.getTransaction().rollback();
}
em.getTransaction().commit();
em.close();
So, it's ok, I can save some object to db.
BUT If I want to remove item, I am getting an exception java.lang.IllegalStateException: Transaction not active.
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.remove(OBJECT TO REMOVE); //REALLY EXIST IN DB
} catch (Exception e) {
em.getTransaction().rollback();
}
em.getTransaction().commit();
em.close();
Can you help me with this? I don't know what it is....
EDIT: I found some code on google and I tried it:
em.getTransaction().begin();
em.remove(em.merge(OBJECT TO REMOVE));
em.getTransaction().commit();
And it worked for me!
Per Javadocs, entityManager.remove only works with Managed entities and if called on detached entities it will result in IllegalStateException.
So in your case your are calling em.remove on a detaced object and it is resulting in IllegalStateException and your catch block is catching it but your are not printing it. You may want to print the stacktrace in the catch block and this should show the IllegalStateException.
And finally after catching the exception you are still proceeding with commit on an rollbacked transacation and this is resulting in the exception you are seeing.
And the reason why em.remove(em.merge(object)) is working should be clear now. em.merge results in fetching the object from the database and so it becomes a managed entity and calling a remove method on managed entity results in successfully deleting it.
You can try using a Repository using save and remove methods for your transactions. It is a safer way.
#ApplicationScoped
#Repository
public abstract class MyEntityRepository implements EntityRepository<MyEntity, Long>, EntityManagerDelegate<MyEntity> {
}
Related
I have this method to delete the entity selected in the list. but when called generates this error and I can not see why.
java.lang.IllegalArgumentException: Entity must be managed to call
remove: HP Envy 15, try merging the detached and try the remove again.
public void delete(Stock stock){
EntityManager em = ConnectionFactory.createEntityManager();
em.getTransaction().begin();
em.detach(stock);
em.remove(stock);
em.getTransaction().commit();
em.close();
}
I've read other related posts
Entity must be managed to call remove
IllegalArgumentException: Entity must be managed to call remove
You can't remove the entity if it is not attached. If the entity is still attached, you can remove it as-is. If it is no longer attached, you can re-attach it using merge:
if (!em.contains(stock)) {
stock = em.merge(stock);
}
em.remove(stock);
Very thanks guys
You helped me to heal my head ache
Here is the code after correcting the error
EntityManager em = ConnectionFactory.createEntityManager();
em.getTransaction().begin();
if (!em.contains(stock)) {
current = em.merge(stock);
}
em.remove(current);
em.getTransaction().commit();
em.close();
You detach an entity from a session, and then delete it. That won't work.
Try removing em.detach(stock); and pass some entity to the method which is guaranteed to be attached to the session, i.e. fetch something from DB and then delete it at once. If that works, you are using your method in a wrong way, most likely with detached or just-created entities.
remove the
em.detach(stock);
detach removes your entity from the entityManager
Why do you detach the object ? An IllegalArgumentException is thrown by detach if the argument is not an entity object.
If the argument stock is managed by entity manager, delete the detach line, else merge the entity.
Try this:
public void delete(Stock stock){
EntityManager em = ConnectionFactory.createEntityManager();
em.getTransaction().begin();
Stock mStock2 = em.merge(stock);
em.remove(mStock2);
em.getTransaction().commit();
em.close();
}
I'm trying to save data using Hibernate. Everything happens within the same session. The logic is following :
1) Begin a transaction and try to save :
try
{
session.getTransaction().begin();
session.save(result);
session.getTransaction().commit();
}
catch (Exception e)
{
session.getTransaction().rollback();
throw e;
}
2) If a new record violates integrity constraint catch an exception in the outer wrapper method, open another transaction and query more data
catch (ConstraintViolationException e)
{
if ("23000".equals(e.getSQLException().getSQLState()))
{
...
session.getTransaction().begin();
Query query = session.createQuery("from Appointment a where a.begin >= :begin and a.end <= :end");
query.setDate("begin", date);
query.setDate("end", DateUtils.addDays(date, 1));
List results = query.list();
session.getTransaction().commit();
The problem is when the second transaction performs query.list it throws an exception that should'be been linked with the previous transaction.
SQLIntegrityConstraintViolationException: ORA-00001: unique constraint
Should I query data from another session or what's the other way to isolate two transactions from each other?
Thanks!
You should not use the same session if you get an exception, you have to close the session and use a different session for your second operation. This is given in hibernate documentation:
13.2.3 Exception Handling
If the Session throws an exception, including any SQLException,
immediately rollback the database transaction, call Session.close()
and discard the Session instance. Certain methods of Session will not
leave the session in a consistent state. No exception thrown by
Hibernate can be treated as recoverable. Ensure that the Session will
be closed by calling close() in a finally block.
Hope the Exception class is base for all types of exceptions, hence if it is placed before it will be catched always and rest of the exception handling is isolated.
Can you try to replce session.save() with session.persist method, hope this might resolve your problem. Refer following link for more details about both methods.
What's the advantage of persist() vs save() in Hibernate?
I have a table with the field 'nom' with the unique constraint and when I test to insert a value of this field that already exists in the table the org.hibernate.exception.ConstraintViolationException is thrown. Then after all my persisting I get a Transaction already active Exception.
this is my persisting method in a Dao class
public void persist(E entity) throws Exception {
EntityTransaction tr=entityManager.getTransaction() ;
tr.begin();
entityManager.persist(entity);
tr.commit();
}
and here the code where I catch the exception
try {
rd.persist(r);
} catch (Exception e) {
e.printStackTrace();
}
How Can I solve this Transaction problem ?
Instead of explicitly opening the transaction you could allow the framework to handle the transaction (like in spring you can use the #transactional). But if not it looks like the code has a begin and a commit in case it is successful, try adding a tr.rollback() in the persist method using a finally (or you could even check whether the transaction is still active using the tr.isActive() method.
There is no need to do anything with Transaction, because it is handled by Spring.
I met "Transaction already active". Though I think what caused it is different with your problem, I think my answer should help someone.
For example:
// Transaction handled by Spring
Session session = sessionFactory.getCurrentSession();
...
return;
------------------------------------------------------------
// Transaction handled by yourself
Session session = sessionFactory.openSession();
Transcation tr = session.beginTransaction();
...
tr.commit();
session.close();
return;
I have a web service method that uses EclipseLink JPA. This method basically inserts data into the database. Something like :
public void insert(parameters....)
{
em.getTransaction().begin();
em.persist(employee);
em.getTransaction().commit();
// em.close();
}
Now at the client end, i have a loop that performs inserts per iteration :
for(......)
{
websrvice.insert(parameters...)
}
After the first iteration, i get a "No transaction is currently active" exception.
Then i thought of putting a Thread.sleep(2000) after each iteration which solves the problem.
So intuitively, this could be because another transaction is trying to commit before the latter is completed which causes the error. But then again i think, why would the second insert even start when the first isn't completed ? confused.
You shouldnt close the entity manager at the end of your transaction.
Remove this line:
em.close();
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#close()
"Close an application-managed entity manager. After the close method has been invoked, all methods on theEntityManager instance and anyQuery and TypedQuery objects obtained from it will throw the IllegalStateException except forgetProperties, getTransaction,and isOpen (which will return false)"
Edit:
Try using the transaction returned by the first getTransaction call, rather than invoking this method twice:
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(employee);
transaction.commit();
Maybe a stupid question, but is it necessary to make a rollback on a transaction in the catch-block if the EntityManager.merge() throws an exception?
Or does the exception itself mean that the merge won´t work so that next time I run commit the previous changes that throwed the exception won´t apply?
Example:
public void setPerson(Person person) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyLib");
EntityManager em = emf.createEntityManager();
try {
if(!em.getTransaction().isActive()){
em.getTransaction().begin();
}
em.merge(person);
em.getTransaction().commit();
emf.getCache().evict(Person.class); // clear Person cache
} catch (Exception ex){
em.getTransaction().rollback(); // Is this necessary?
} finally {
em.close();
}
}
The answer depends on the details of em.merge(person) method and the implementation of your database driver.
If that method only performs one update statement, then the rollback is superfluous. If however it may run multiple updates, then it's not that clear.
I personally would keep it there
If the rollback is removed and your merge method errors our after some updates are done but others are not, then closing a database connection without explicit commit or rollback will either commit or rollback the transaction, depending on the driver implementation. According to the javadoc for java.sql.Connection, the behaviour depends on the implementation. Hence you may end up committing partial updates if you do not rollback yourself on error.