JPA - When to use getTransaction() when persisting

2020-02-18 20:42发布

I've recently started working with JPA on the Google App Engine. In reading some examples, I've noticed a couple of variations in the way objects are persisted. In one case, I've seen something like this:

entityManager.getTransaction().begin();
entityManager.persist(object);
entityManager.getTransaction().commit();

In other cases, I don't see the use of getTransaction(). I simply see entityManager.persist(object). When is it appropriate to use getTransaction()?

4条回答
何必那么认真
2楼-- · 2020-02-18 21:21

Google App Engine has its transaction management (https://developers.google.com/appengine/docs/java/datastore/transactions) but the JPA transaction interface isn't aware of some of the GAE underlying functionalities (i.e. entity groups).

So it’s up to your application to decide which operations to perform in a transaction and which not. You should put in a transaction operations that have to be executed atomically.

Remember as a best practice to perform cascading actions and relationship operations in a transaction because JPA might trigger many queries and it could lead to an inconsistent data situation.

Example of using transaction with JPA2:

import javax.persistence.EntityTransaction;


EntityTransaction txn = em.getTransaction();
txn.begin();
try {
    //do something with your database
    txn.commit();
} 
finally {
   if (txn.isActive())
      txn.rollback(); 
}
查看更多
ら.Afraid
3楼-- · 2020-02-18 21:29

You'd use getTransaction() when you're explicitly handling the transactions in your application. On the other hand, if you let the container handle the transactions for you, it won't be necessary to explicitly begin/end transactions. Essentially, we're dealing with the difference between Container Managed Transactions (CMT) and Bean Managed Transactions (BMT).

In general, you'd use BMT when you need more control over the transactional processing, or when there are additional technical requirements (for instance, two-phase commits, distributed transactions, XA transactions) that can't be met by using CMT. Also, you'd use BMT when your applications is deployed outside of an application server and relies on Java SE.

查看更多
贪生不怕死
4楼-- · 2020-02-18 21:34

In GAE there is no Java EE/JTA so ignore terms such as bean managed transaction (BMT), and container managed transactions (CMT).

Your work is either transactional (where you want multiple objects to go to the datastore at once, or all to fail - this is where you have getTransaction() used), or nontransactional (where everything goes to the datastore one by one, and the failure of one persist doesn't affect others - this is where you just call persist()/merge()/remove()).

查看更多
【Aperson】
5楼-- · 2020-02-18 21:39

If you use container managed EntityManager then you're using JTA transactions. Hence, you don't need to (more precisely - you can not) interfere with EntityManager's transactions fetched using entityManager.getTransaction(). The JTA starts and commits your transaction.

If you use application managed EntityManager and you don't want to be in part of JTA transaction, then you need to manage them for yourself (it's called a resource-local entity manager).

Most typically, application managed EntityManager which works with EntityManager.getTransaction() is used in Java SE environment.

EDIT: You might be interested in secion 7.5 Controlling Transactions from the JPA 2.0 specification.

查看更多
登录 后发表回答