पीओजेओ के लिए लेनदेन

मैं एक विधि लागू कर रहा हूं जो कुछ ऐसा करता है:

...
try {
   myPojo.setProperty("foo");
   myService.execute(myPojo);
} catch (Exception e) {
   logger.error(e.getMessage(), e);
}
...

यदि इस प्रयास से मेरी सेवा द्वारा कुछ अपवाद फेंक दिया गया है तो पॉजो संपत्ति पर ब्लॉक का नया मूल्य होगा। क्या pojo परिवर्तनों के लिए एक प्रकार का लेनदेन शुरू करने का कोई तरीका है और कुछ गलत होने पर इसे वापस रोल करें?

कुछ इस तरह:

PojoTransaction pt = startPojoTransaction();
transactionedPojo = pt.handleByTransaction(myPojo);
try {
   transactionedPojo.setProperty("foo");
   myService.execute(transactionedPojo);
   pt.commit;
} catch (Exception e) {
   logger.error(e.getMessage(), e);
}

या कुछ इसी तरह ...

0
जोड़ा
विचारों: 1

3 उत्तर

Take a look at the Memento Pattern, it includes a Java example.
http://en.wikipedia.org/wiki/Memento_pattern

0
जोड़ा

सवाल थोड़ा अस्पष्ट है, लेकिन ऐसा लगता है कि आप लेनदेन प्रबंधन के लिए बुनियादी डिजाइन पैटर्न के साथ कुश्ती कर रहे हैं। आपको अनुभव से बहुत लाभ होगा जो यहां इस्तेमाल किए गए पैटर्न के उत्पादन में चला गया है:

http://static.springsource.org /spring/docs/3.0.x/spring-framework-reference/html/transaction.html

शायद वसंत लेनदेन प्रबंधन वैसे भी आपके प्रोजेक्ट के लिए उपयुक्त होगा।

0
जोड़ा

मैंने इस विचार के साथ खिलवाड़ किया, यह बिल्कुल सही है, अवधारणा का एक साधारण सबूत है। इस कार्यान्वयन में नुकसान हैं:

  • यह केवल दिए गए स्रोत के पैरामीटर रहित कन्स्ट्रक्टर को कॉल करने का प्रयास करता है लक्ष्य-प्रतिलिपि बनाने के लिए ऑब्जेक्ट, सही कन्स्ट्रक्टर का चयन करने के लिए कुछ तर्क की आवश्यकता होगी (या केवल क्लोनबेल का समर्थन करें?)
  • केवल वर्ग में घोषित फ़ील्ड की प्रतिलिपि, सुपरक्लास से नहीं (इस समस्या को विरासत के पेड़ के माध्यम से चलने और किसी भी सुपरक्लास फ़ील्ड की प्रतिलिपि बनाने का हल किया जा सकता है)
  • यदि फ़ील्ड जटिल प्रकार हैं, तो केवल संदर्भ-ऑब्जेक्ट पर संदर्भों की प्रतिलिपि बनाई गई है, इसलिए उनमें से कोई भी परिवर्तन लेन-देन नहीं होगा, क्योंकि स्रोत और लक्ष्य दोनों एक ही उदाहरण साझा करते हैं (नेस्टेड ऑब्जेक्ट्स की प्रतिलिपि बनाकर हल करने योग्य) अपने मूल्यों की प्रतिलिपि बनाने के लिए, स्रोत से शुरू होने वाले पूरे ऑब्जेक्ट-ग्राफ़ के माध्यम से चलने की आवश्यकता होती है, और उसके बाद इसे प्रतिबद्ध समय पर विपरीत बनाते हैं)

लेकिन, यहां से सुधार, मेरा मानना ​​है कि यह बहुत उपयोगी हो सकता है। यहां पीओसी है:

import java.lang.reflect.Field;

import org.junit.Assert;
import org.junit.Test;

public class PojoTransactionTest
{
    public static class PojoTransaction
    {
        /**
         * This is the original (unmodified) object
         */
        private T source;

        /**
         * This is the object modified by within the transaction
         */
        private T target;

        /**
         * Creates a new transaction for the given source object
         * @param source    Source object to modify transactionally
         */
        public PojoTransaction(T source)
        {
            try
            {
                this.source = source;
                this.target = (T)source.getClass().newInstance(); //Note: this only supports parameterless constructors

                copyState(source, target);
            }
            catch(Exception e)
            {
                throw new RuntimeException("Failed to create PojoTransaction", e);
            }
        }

        /**
         * Copies state (member fields) from object to another
         * @param from      Object to copy from
         * @param to        Object to copy to
         * @throws IllegalAccessException
         */
        private void copyState(T from, T to) throws IllegalAccessException
        {
            //Copy internal state to target, note that this will NOT copy fields from superclasses
            for(Field f : from.getClass().getDeclaredFields())
            {
                f.setAccessible(true);
                f.set(to, f.get(from));
            }
        }

        /**
         * Returns the transaction target object, this is the one you should modify during transaction
         * @return Target object
         */
        public T getTransactionTarget()
        {
            return target;
        }

        /**
         * Copies the changes from target object back to original object
         */
        public void commit()
        {
            try
            {
                copyState(target, source);
            }
            catch(Exception e)
            {
                throw new RuntimeException("Failed to change state of original object", e);
            }
        }
    }

    public static class TestData
    {
        private String strValue = "TEST";
        private int intValue = 1;
        private float floatValue = 3.1415f;

        public String getStrValue()
        {
            return strValue;
        }

        public void setStrValue(String strValue)
        {
            this.strValue = strValue;
        }

        public int getIntValue()
        {
            return intValue;
        }

        public void setIntValue(int intValue)
        {
            this.intValue = intValue;
        }

        public float getFloatValue()
        {
            return floatValue;
        }

        public void setFloatValue(float floatValue)
        {
            this.floatValue = floatValue;
        }

    }

    @Test
    public void testTransaction()
    {
        //Create some test data
        TestData orig = new TestData();

        //Create transaction for the test data, get the "transaction target"-object from transaction
        PojoTransaction tx = new PojoTransaction(orig);
        TestData target = tx.getTransactionTarget();
        target.setFloatValue(1.0f);
        target.setIntValue(5);
        target.setStrValue("Another string");

        //Original object is still at the original values
        Assert.assertEquals(1, orig.getIntValue());
        Assert.assertEquals(3.1415f, orig.getFloatValue(), 0.001f);
        Assert.assertEquals("TEST", orig.getStrValue());

        //Commit transaction
        tx.commit();

        //The "orig"-object should now have the changes made to "transaction target"-object
        Assert.assertEquals(5, orig.getIntValue());
        Assert.assertEquals(1.0f, orig.getFloatValue(), 0.001f);
        Assert.assertEquals("Another string", orig.getStrValue());
    }

}
0
जोड़ा