Bean-Managed Transactions

4705 ワード

To control transaction boundaries yourself, you must use the JTA interface javax.transaction.UserTransaction. The javax.transaction.UserTransaction interface enables you to programmatically control transactions. Here is what the javax.transaction.UserTransaction interface looks like:
public interface javax.transaction.UserTransaction
    public void begin();
    public void commit();
    public int getStatus();
    public void rollback();
    public void setRollbackOnly();
    public void setTransactionTimeout(int);
}

 
begin() : Begins a new transaction. This transaction becomes associated with the current thread.
commit() : Runs the two-phase commit protocol on an existing transaction associated with the current thread. Each resource manager will make its updates durable.
getStatus() : Retrieves the status of the transaction associated with this thread.
Rollback() : Forces a rollback of the transaction associated with the current thread.
setRollbackOnly() : Calls this to force the current transaction toroll back. This will eventually force the transaction to abort.
setTransactionTimeout(int) : The transaction timeout is the maximum amount of time that a transaction can run before it’s aborted. This is useful for avoiding deadlock situations, when precious resources are being held by a transaction that is currently running.
 
JTA also defines a number of constants that indicate the current status of a transaction. You will be returned one of these constants when you call the UserTransaction.getStatus() method:
public interface javax.transaction.Status {
    public static final int STATUS_ACTIVE;
    public static final int STATUS_NO_TRANSACTION;
    public static final int STATUS_MARKED_ROLLBACK;
    public static final int STATUS_PREPARING;
    public static final int STATUS_PREPARED;
    public static final int STATUS_COMMITTING;
    public static final int STATUS_COMMITTED;
    public static final int STATUS_ROLLING_BACK;
    public static final int STATUS_ROLLEDBACK;
    public static final int STATUS_UNKNOWN;
}

STATUS_ACTIVE : A transaction is currently active.
STATUS_NO_TRANSACTION : No transaction is active.
STATUS_MARKED_ROLLBACK : The current transaction will eventually abort because it’s been marked for rollback. This could be because some party called UserTransaction.setRollbackOnly().
STATUS_PREPARING : The current transaction is preparing to be committed (during Phase One of the two-phase commit protocol).
STATUS_PREPARED : The current transaction has been prepared to be committed (Phase One is complete).
STATUS_COMMITTING : The current transaction is in the process of being committed right now (during Phase Two).
STATUS_COMMITTED : The current transaction has been committed (Phase Two is complete).
STATUS_ROLLING_BACK : The current transaction is in the process of rolling back.
STATUS_ROLLEDBACK : The current transaction has been rolled back.
STATUS_UNKNOWN :  The status of the current transaction cannot be determined.
 
We now show you how to write an enterprise bean that uses bean-managed transactions. To do this, we’ll use teller bean. The transferFunds() method of the teller bean needs to use transactions to make sure that the updates to the bank account entities are done as part of the same transaction. Let us see how we do this by using javax.transaction.UserTransaction methods.
import javax.ejb.*;
import javax.annotation.Resource;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import javax.transaction.UserTransaction;

@Stateless()
@TransactionManagement(javax.ejb.TransactionManagementType.BEAN)
public class TellerBean implements Teller {
    @PersistenceContext private EntityManager em;
    @Resource private javax.transaction.UserTransaction userTx;
    public void transferFunds(float amount, String fromAccount, String toAccount) {
        // Lookup for accts with the provided account Ids
        try {
             userTx.begin();
             BankAccount acct1 = em.find(BankAccount.class, fromAccount);
             BankAccount acct2 = em.find(BankAccount.class, toAccount);
             if (acct1.balance < amount) userTx.rollback();
             acct1.withdraw(amount);
             acct2.deposit(amount);
             em.persist(acct1);
             em.persist(acct2);
             userTx.commit();
        } catch (Exception e) {
             System.out.println(“Exception occurred during transfer of funds.” + e.getMessage());
        }
    }
}