JTA & Transaction basic information

http://www.onjava.com/pub/a/onjava/2001/05/23/j2ee.html

- Appserver use transaction manager to enalble and application component to perform
  transactional access across multiple EIS resource managers.(distributed system)
  * Appserver provides transaction service
  * The transaction manager supports JTA XAResource.
  * Every EIS resource must implement the JTA XAResource to be as a interface in order to
    be controlled by transaction manager.

- Supporting access to a single JDBC database within a transaction(multiple connections to
  the same database are allowed) is required by J2EE platform.

- Supporting transaction across multiple(same/different) databse is not required.
  2PC is maybe not provided by J2EE product.

- Three pheromena about database access
  - Dirty reads

    1> columnA = 1
    2> T1 begins
    3>    T2 begins
    4>    T2 change columnA to 2
    5> T1 read columnA -- 2
    6>    T2 rollback
    7> T1 holds a dirty data - 2
    8> T1 does more..
    9> T1 commit

    (In T1, T1 using a uncommited data)
 
  - Nonrepeatable reads
 
    1> columnA = 1
    2> T1 begins
    3> T1 read columnA - 1
    4>    T2 begains
    5>    T2 change columnA to 2
    6>    T2 commit
    7> T1 re-read columnA - 2
    8> T1 does more ..
    9> T1 commit

   (In T1, the columnA's values read twice are different)
   
  - Phantom reads

    1> TableA has 50 records
    2> T1 begins
    3> T1 query db, 50 records returned staisfies conditon1
    4>    T2 begin
    5>    T2 insert 1 record satisfies the condition1
    6>    T2 commit
    7> T1 re-search base on the same condition, and 51 records returned
    8> T1 does more..
    9> T1 commit

   (In T1, the records returned of the same 2 query are different)


- Isolation levels

  - TRANSACTION_READ_UNCOMMITTED
    Nothing will be controlled

  - TRANSACTION_READ_COMMITTED
    In a transaction, just data commited can be read

  - TRANSACTION_REPEATABLE_READ
    In a transaction, read same data many times, the returned result will be same

  - TRANSACTION_SERIALIZABLE
    The transaction has exclusive read and update privilege to data by locking it.
    Other transaction can not access (read/write) the data util the holder transaction
    releases data's lock.

 


Isolation level summary
Isolation Level Dirty Read Non Repeatable Read Phantom Read
TRANSACTION_READ_UNCOMMITTED YES YES YES
TRANSACTION_READ_COMMITTED NO YES YES
TRANSACTION_REPEATABLE_READ NO NO YES
TRANSACTION_SERIALIZABLE NO NO NO


- All RDBMS or EIS used by a J2EE application should use the same isolation level for
  consistency reasons since the current J2EE specification does NOT define a standard
  way to set isolation levels when an EIS is accessed via JTA transactions. If a J2EE
  product does not provide a way to configure teh isolation level, the RDBMS or EIS
  will use the default level, which for most of the RDB is TRANSACTION_READ_COMMITTED

- Strongly recommend not to change the isolation level within a transaction, especially
  some work has already been done, some are to be done. Some EIS will force commit transaction
  if you want to change isolation level in the middle of a transaction

- There are 2 ways to begin a JTA transaction
  1) explicitly using the JTA javax.transaction.UserTransaction interface in your code
  2) implicitly controlled by EJB container if using CMP

 

- Case 1    Stand-alone client -> EJB Container -> RDBMS/EIS
  Transaction support in applets and application clients is not required by the J2EE platform
  This is a added value of the J2EE product, you should make sure whether the appserver you
  are using can support it.

- Case 2   Browser -> Web Container -> RDBMS/EIS
  It's important to keep in mind that a web component like a servlet may only start a
  transaction in its servic() method. Moreover, the transaction can not span across web
  requests.

  - Code Snippet
    Context myCntxt = new InitialContext();
    UserTransaction ut = (UserTransaction) myCntxt.lookup("java:comp/UserTransaction");
    ut.begin();
    // perform transactional work here
    ut.commit();
 
  - The following guidelines are recommended for handling interactions in web components
    between JTA transactions, threads, and JDBC connections.
    - JTA transactions should start and complete only from the thread in which the service
      method is called. Additional threads created in the servlet should not attempt to start
      any JTA transaction.
    - JDBC connections may be acquired and released by a thread other than the service method  
      thread, but should not be shared between threads.
    - JDBC Connection objects should not be stored in static fields.
    - For web components implementing the SingleThreadModel, JDBC Connection objects may be
      stored in class instance fields.
    - For web components (servlets) not implementing the SingleThreadModel, JDBC Connection
      objects should not be stored in class instance fields and should be acquired and released
      within the same invocation of the service method.


- Case 3   browser -> web container -> ejb container -> RDBMS/EIS
  - Code snippet used by BMP
    UserTransaction ut = ejbContext.getUserTransaction();
    ut.begin();
    // Transactional work is done here
    ut.commit();
  - The following example illustrates a business method of a typical session bean that performs
    a bean managed transaction involving both a database connection and a JMS connection.

    public class MySessionEJB implements SessionBean {
        EJBContext ejbContext;
        public void someMethod(...) {
            javax.transaction.UserTransaction ut;
            javax.sql.DataSource ds;
            java.sql.Connection dcon;
            java.sql.Statement stmt;
            javax.jms.QueueConnectionFactory qcf;
            javax.jms.QueueConnection qcon;
            javax.jms.Queue q;
            javax.jms.QueueSession qsession;
            javax.jms.QueueSender qsender;
            javax.jms.Message message;
            InitialContext initCtx = new InitialContext();

            // obtain db conn object and set it up for transactions
            ds = (javax.sql.DataSource)
            initCtx.lookup("java:comp/env/jdbc/Database");
            dcon = ds.getConnection();
            stmt = dcon.createStatement();

            // obtain jms conn object and set up session for transactions
            qcf = (javax.jms.QueueConnectionFactory)
            initCtx.lookup("java:comp/env/jms/qConnFactory");
            qcon = qcf.createQueueConnection();
            qsession = qcon.createQueueSession(true,0);
            q = (javax.jms.Queue)
            initCtx.lookup("java:comp/env/jms/jmsQueue");
            qsender = qsession.createSender(q);
            message = qsession.createTextMessage();
            message.setText("some message");
            //
            // Now do a transaction that involves the two connections.
            //
            ut = ejbContext.getUserTransaction();
            // start the transaction
            ut.begin();
            // Do database updates and send message. The Container
            // automatically enlists dcon and qsession with the
            // transaction.
            stmt.executeQuery(...);
            stmt.executeUpdate(...);
            stmt.executeUpdate(...);
            qsender.send(message);
            // commit the transaction
            ut.commit();

            // release connections
            stmt.close();
            qsender.close();
            qsession.close();
            dcon.close();
            qcon.close();
        }
        ...
    }

  - The following example illustrates a stateful session bean that retains transaction context
    across three client calls, invoked in the order {method1, method2, and method3}.

    public class MySessionEJB implements SessionBean {
        EJBContext ejbContext;
        javax.sql.DataSource ds1;
        javax.sql.DataSource ds2;
        java.sql.Connection con1;
        java.sql.Connection con2;
        public void method1(...) {
            java.sql.Statement stmt;
            InitialContext initCtx = new InitialContext();
            // obtain user transaction interface
            ut = ejbContext.getUserTransaction();
            // start a transaction
            ut.begin();
            // make some updates on con1
            ds1 = (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/Database1");
            con1 = ds1.getConnection();
            stmt = con1.createStatement();
            stmt.executeUpdate(...);
            stmt.executeUpdate(...);
            //
            // The Container retains the transaction associated with the
            // instance to the next client call (which is method2(...)).
        }
        public void method2(...) {
            java.sql.Statement stmt;
            InitialContext initCtx = new InitialContext();
            // make some updates on con2
            ds2 = (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/Database2");
            con2 = ds2.getConnection();
            stmt = con2.createStatement();
            stmt.executeUpdate(...);
            stmt.executeUpdate(...);
            // The Container retains the transaction associated with the
            // instance to the next client call (which is method3(...)).
        }
        public void method3(...) {
            java.sql.Statement stmt;
            // obtain user transaction interface
            ut = ejbContext.getUserTransaction();
            // make some more updates on con1 and con2
            stmt = con1.createStatement();
            stmt.executeUpdate(...);
            stmt = con2.createStatement();
            stmt.executeUpdate(...);
            // commit the transaction
            ut.commit();
            // release connections
            stmt.close();
            con1.close();
            con2.close();
        }
        ...
    }

  - This is the transaction started in method1 and committed in method3.
    public class MySessionEJB implements SessionBean {
        EJBContext ejbContext;
        InitialContext initCtx;
        public void method1(...) {
            java.sql.Statement stmt;
            // obtain user transaction interface
            ut = ejbContext.getUserTransaction();
            // start a transaction
            ut.begin();
        }

        public void method2(...) {
            javax.sql.DataSource ds;
            java.sql.Connection con;
            java.sql.Statement stmt;
            // open connection
            ds = (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/Database");
            con = ds.getConnection();
            // make some updates on con
            stmt = con.createStatement();
            stmt.executeUpdate(...);
            stmt.executeUpdate(...);
            // close the connection
            stmt.close();
            con.close();
        }
        public void method3(...) {
            // obtain user transaction interface
            ut = ejbContext.getUserTransaction();
            // commit the transaction
            ut.commit();
        }
        ...
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值