Java design pattern-Transaction Processing

Source: Internet
Author: User
Transaction processing is one of the most important issues for enterprise applications. J2EE provides complete transaction management capabilities through JTA, including the management capabilities of multiple transactional resources. However, most applications run on a single transactional resource (a database) and do not need global transaction services. The local transaction service is sufficient (such as JDBC transaction management ).
This article does not discuss what transaction processing methods should be used, but mainly aims to discuss how to design transaction services more elegantly. Take JDBC transaction as an example. For more information about Dao, factory, proxy, and decorator, see related documents.
Maybe you have heard that the transaction processing should be done at the service layer, maybe you are doing the same, but do you know why? Why not store the data in the DaO layer for transaction processing. The obvious reason is that each method of the business layer interface is sometimes a User case. It needs to call different Dao objects to complete a business method. For example, simply taking the final order for purchasing books in an online bookstore as an example, the business method is to first call the bookdao object (usually generated by the DaO factory) and check whether there is inventory balance, obtain the price information of the book, and then call customerdao to deduct the corresponding fees from the account and record the information, and then other services (notify the administrator, etc ). The simplified business process is like this:
Note that the connection processing is ignored in our example. You only need to ensure that the same connection is obtained in the same thread (threadlocal can be used for implementation ):

The first is the business interface, for the interface, rather than for class programming:

  1.  
  2. Public InterfaceBookstoremanager {
  3. Public BooleanBuybook (StringBookid,IntQuantity)ThrowsSystemexception;
  4. ... Other Business Methods
  5. }

What is the implementation class of the business interface ?? Business Objects:

  1.  
  2. Public ClassBookstoremanagerimplImplementsBookstoremanager {
  3. Public BooleanBuybook (StringBookid)ThrowsSystemexception {
  4. Connection conn = connectionmanager. getconnection ();// Obtain the database connection
  5. BooleanB =False;
  6. Try{
  7. Conn. setautocommit (False);// Cancel automatic submission
  8. Bookdao = daofactory. getbookdao ();
  9. Customerdao = daofactory. getcustomerdao ();
  10. // Try to fetch books from stock
  11. If(Bookdao. performanceinventory (Conn, bookid, quantity )){
  12. Bigdecimal price = bookdao. getprice (bookid );// Get the price
  13. // Deduct the price * quantity fee from the customer account
  14. B =
  15. Customerdao. performanceaccount (Conn, Price. Multiply (NewBigdecimal (Quantity ));
  16. ....
  17. Other business methods, such as notifying administrators and generating orders.
  18. ...
  19. Conn. Commit ();// Submit the transaction
  20. Conn. setautocommit (True);
  21. }
  22. }Catch(Sqlexception e ){
  23. Conn. rollback ();// Rollback the transaction due to an exception
  24. Con. setautocommit (True);
  25. E. printstacktrace ();
  26. Throws NewSystemexception (E );
  27. }
  28. ReturnB;
  29. }
  30. }
  31.  

Then the business representative Factory:

  1.  
  2. Public Final ClassManagerfactory {
  3. Public StaticBookstoremanager getbookstoremanager (){
  4. Return NewBookstoremanagerimpl ();
  5. }
  6. }

This design is very suitable for simple activities in Dao. A small system in our project also adopts this design scheme, but it is not suitable for large-scale applications. First, do you smell the bad smell with repeated code? Set autocommit to false every time, submit the job, roll back the job with an exception, and throw the package exception to the upper layer. If it is too long to write, can it be eliminated? Second, the business representative object now knows all the details of its internal transaction management, which is inconsistent with the original intention of our design business representative object. For the business representative object, it is quite appropriate to understand a transaction-related business constraint, but it is not appropriate to let it be responsible for implementing them. Again, have you ever thought about nested Business Object scenarios? The business represents mutual calls between objects and layer-by-layer nesting. What do you do now? You need to know that, in our current way, each business method is in a separate transaction context (transaction context), and each other calls to form a nested transaction. What should you do now? Maybe the solution is to re-write it, and combine different business methods into a big bully and package it in a transaction context.

We have a more elegant design to solve such problems. If we give the control of the transaction context to an external object that is known by the business representative object, Dao and other component. When a business indicates that a method of an object needs transaction management, it prompts another object that wants to start a transaction. The External Object obtains a connection and starts a database transaction. That is to say, the transaction control is extracted from the service layer. When the web layer calls a service at the service layer to represent an object, the returned service object is a service object packaged (or a proxy) through the transaction context external object. This proxy object sends the request to the original service representative object, but implements transaction control on the business method. So how can we achieve this effect? The answer is the dynamic proxy technology introduced in jdk1.3. Dynamic proxy technology can only act as a proxy, which is why we need a business interface bookstoremanager.
First, we introduce this transaction context external object. Its code is actually very simple. If you do not know about dynamic proxy technology, please read other materials first.

  • ImportJava. Lang. reflect.Invocationhandler;
  • ImportJava. Lang. reflect.Method;
  • ImportJava. Lang. reflect.Proxy;
  •  
  • ImportJava. SQL.Connection;
  •  
  • ImportCom. strutslet. Demo. Service. systemexception;
  •  
  • Public Final ClassTransactionwrapper {
  •  
  • /**
  • * The original business representative object is decorated, and a proxy object with the same interface as the business representative object is returned.
  • */
  • Public Static ObjectDecorate (ObjectDelegate ){
  • Return Proxy. Newproxyinstance (delegate. getclass (). getclassloader (),
  • Delegate. getclass (). getinterfaces (),NewXawrapperhandler (
  • Delegate ));
  • }
  • // Dynamic proxy technology
  • Static Final ClassXawrapperhandlerImplements Invocationhandler{
  • Private Final ObjectDelegate;
  •  
  • Xawrapperhandler (ObjectDelegate ){
  • This. Delegate = delegate;
  • }
  • // For simplicity, the packaging business represents all the business methods of the object
  • Public ObjectInvoke (ObjectProxy,MethodMethod,Object[] ARGs)
  • Throws Throwable{
  • ObjectResult =Null;
  • ConnectionCon = connectionmanager. getconnection ();
  • Try{
  • // Start a transaction
  • Con. setautocommit (False);
  • // Call the Business Method of the original Business Object
  • Result = method. Invoke (delegate, argS );
  • Con. Commit ();// Submit the transaction
  • Con. setautocommit (True);
  • }Catch(ThrowableT ){
  • // Rollback
  • Con. rollback ();
  • Con. setautocommit (True);
  • Throw NewSystemexception (t );
  • }
  •  
  • ReturnResult;
  • }
  • }
  • }

    As we can see, this object only extracts the transaction control part of the business method that requires transaction control from the business object. Please note that the business means that the method of calling the object itself will not start new transactions, because these calls will not be passed to the proxy object. In this way, we can remove the taste of repetition. In this case, our business representative object is changed:

    1.  
    2. Public ClassBookstoremanagerimplImplementsBookstoremanager {
    3. Public BooleanBuybook (StringBookid)ThrowsSystemexception {
    4. Connection conn = connectionmanager. getconnection ();// Obtain the database connection
    5. BooleanB =False;
    6. Try{
    7. Bookdao = daofactory. getbookdao ();
    8. Customerdao = daofactory. getcustomerdao ();
    9. // Try to fetch books from stock
    10. If(Bookdao. performanceinventory (Conn, bookid, quantity )){
    11. Bigdecimal price = bookdao. getprice (bookid );// Get the price
    12. // Deduct the price * quantity fee from the customer account
    13. B =
    14. Customerdao. performanceaccount (Conn, Price. Multiply (NewBigdecimal (Quantity ));
    15. ....
    16. Other business methods, such as notifying administrators and generating orders.
    17. ...
    18. }
    19. }Catch(Sqlexception e ){
    20. Throws NewSystemexception (E );
    21. }
    22. ReturnB;
    23. }
    24. ....
    25. }
    1. As you can see, at this time, the business representative object focuses on implementing the business logic. It no longer cares about the transaction control details and delegates them all to external objects. The business representative factory also needs to be modified to return two types of business representative objects:

    1.  
    2. Public Final ClassManagerfactory {
    3. // Return a encapsulated object with transaction control capability
    4. Public StaticBookstoremanager getbookstoremanagertrans (){
    5. Return(Bookstoremanager) transactionwrapper
    6. . Decorate (NewBookstoremanagerimpl ());
    7. }
    8. // Original Version
    9. Public StaticBookstoremanager getbookstoremanager (){
    10. Return NewBookstoremanagerimpl ();
    11. }
    12. ......
    13. }
    1. We provide two different object generation methods on the business representative Factory: one for creating encapsulated objects, which creates a new transaction for each method call; another version is used to create unwrapped versions. It is used to join existing transactions (for example, other services represent the business methods of objects) and solve the problem of nested businesses representing objects.
      Our design is not elegant enough. For example, by default, all the methods that represent the object will be encapsulated in a transaction context. But the fact is that many methods may not need to deal with the database. If we can configure which methods require transaction declarations and which do not need transaction management, it will be more perfect. The solution is also very simple. You can configure the configuration in an xml configuration file and make a decision when calling the configuration file. Speaking of this, spring will probably realize that this is not declarative transaction control? As such, transaction control is a service of AOP, and spring declarative transaction management is implemented through AOP. The implementation of AOP includes: Dynamic proxy technology, bytecode generation technology (such as cglib Library), Java code generation (used in early EJB ), modify the class loader and source code-level mixed weaving (aspectj. Here we use the dynamic proxy technology, which can only be used for interface proxy; For Class dynamic proxy, cglib library can be used.
       
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.