POJO的交易

我正在实现一个类似的方法:

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

如果我的服务从pojo属性的此try块抛出一些exception将具有新值。 是否有某种方法可以为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); } 

或类似的东西……

我玩弄了这个想法,这远非完美,只是一个简单的概念certificate。 这个实现有一些陷阱:

  • 它只试图调用给定源对象的无参数构造函数来创建目标副本,需要一些逻辑来选择正确的构造函数(或者只支持Cloneables?)
  • 只复制在类中声明的字段,而不是复制超类中的字段(可以通过inheritance树遍历并复制任何超类字段来解决此问题)
  • 如果字段是复杂类型,则只将引用复制到target-object,因此对它们的任何更改都不是事务性的,因为源和目标共享同一个实例(通过递归创建嵌套对象的副本并复制它们的值来解决) ,需要遍历整个对象图,从源头开始,然后在提交时反之亦然)

但是,从这里开始改进,我相信它可以变得非常实用。 这是POC:

 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()); } } 

看一下Memento Pattern,它包含一个Java示例。
http://en.wikipedia.org/wiki/Memento_pattern

问题有点模糊,但听起来你正在努力解决交易管理的基本设计模式。 您将从生成此处使用的模式的经验中获益匪浅:

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

也许Spring Transaction管理无论如何都适合您的项目。