简体   繁体   中英

Can't do DELETE in Java, JPA

I have the following code. The problem is that on the second line I get "org.apache.openjpa.persistence.TransactionRequiredException: Can only perform operation while a transaction is active"

The first line executed fine. What is my mistake?

//em is some EntityManager
String s = (String)em.createQuery("SELECT something FROM something WHERE something = something").getSingleResult();

em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();

Read operations are handled differently from write operations in JPA. Write operations (be they create, updates or deletes) typically need to happen in the context of a transaction. The transaction boundary demarcates the calls you make to the session or entity manager, and defines when the transaction will be committed, (for example it could call commit on method call exit, when using container managed transactions ).

For JPA, all calls to persist, remove, refresh and merge need to be done in a transaction. Query calls need to be performed in a transaction if they invoke executeUpdate . And calling getResultList() or getUniqueResult() needs to be done in the context of a transaction if lock mode is not LockMode.NONE .

Depending on your application needs you will use either container managed transactions (CMT) , or bean managed transactions (BMT) .

For CMT, make sure your persistence unit defines your datasource as JTA, and then annotate your class or method appropriately. For example:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="sample" transaction-type="JTA">
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>

And then annotate your class/method with the appropriate transaction type:

@ TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doSomething() {
    em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();
}

If using BMT, then you have to explicitly manage the transactions:

public void doSomething() throws Exception {
    em.getTransaction().begin();

    try {
        em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();
    } catch(Exception e) {
        em.getTransaction().setRollbackOnly();
    } finally {
        em.getTransaction().commit();
    }
}

You can only modify data in the database while a transaction is active. You start a transaction with

em.getTransaction().begin();

and end it successfully with

em.getTransaction().commit();

or end it rolling back the changes with

em.getTransaction().rollback();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM