首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在生成唯一序列号(Objectify4)的测试中,XG事务隔离失败

在生成唯一序列号(Objectify4)的测试中,XG事务隔离失败
EN

Stack Overflow用户
提问于 2012-10-22 20:45:07
回答 1查看 217关注 0票数 0

我必须在XG事务中生成一个唯一的发票号,其中包括数据模型中的以下3实体组

  • (toplevel) ContactRoot <-(祖先)<- contact :必须在事务期间将联系人更新为状态客户端
  • (toplevel) CustomerSettings:保存要使用的下一个序列号;只有一个具有固定静态ID的CustomerSettings实例;在事务处理期间必须增加序列号+1
  • (toplevel) InvoiceRoot <-(祖先) <-- 发票:根据CustomerSettings中的序列号分配新的唯一发票号;

这是DAO实现的基本部分(删除了无关的业务规则、检查等):

代码语言:javascript
复制
public void saveInvoice(final Invoice invoice) throws BusinessRuleException {

    final Objectify ofy = ObjectifyService.factory().begin().cache(true);
    ofy.transact(new Work<Void>() {

        @Override
        public Void run() {
            CustomerSettings customerSettings = ofy.load()
                    .key(Key.create(CustomerSettings.class, CustomerSettings.ID)).safeGet();
            Contact contact = ofy.load().key(createContactKey(invoice.getContactId()).safeGet();
            contact.setContactType(ContactType.CLIENT);
            ofy.save().entity(contact).now();
            String invoiceNumber = generateSequence(ofy, customerSettings);
            invoice.setInvoiceNumber(invoiceNumber);
            ofy.save().entity(invoice).now();
            return null;
        }
    });
}

以及生成下一个序列号的简化版本,其中下一个序列号在下一个调用中增加,CustomerSettings必须通过事务方式更新(我已经同步了,但我想这并不是真正有用的):

代码语言:javascript
复制
private synchronized String generateSequence(Objectify ofy, CustomerSettings settings) {
    String ret = "";
    int sequence = settings.getNextSequence();
    settings.setNextSequence(sequence + 1);
    ofy.save().entity(settings).now();
    ret = "" + sequence;
    return ret;
}

这就是我的单元测试对于变量线程计数的情况:

代码语言:javascript
复制
private void test(final int threadCount) throws InterruptedException, ExecutionException {
    final Environment currentEnvironment = ApiProxy.getCurrentEnvironment();
    Callable<String> task = new Callable<String>() {
        @Override
        public String call() {
            ApiProxy.setEnvironmentForCurrentThread(currentEnvironment);
            return generateInvoiceNumber();
        }
    };
    List<Callable<String>> tasks = Collections.nCopies(threadCount, task);
    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    List<Future<String>> futures = executorService.invokeAll(tasks);
    List<String> resultList = new ArrayList<String>(futures.size());
    // Check for exceptions
    for (Future<String> future : futures) {
        // Throws an exception if an exception was thrown by the task.
        resultList.add(future.get());
    }
    // Validate the IDs
    Assert.assertEquals(futures.size(), threadCount);
    List<String> expectedList = new ArrayList<String>(threadCount);
    for (long i = 1; i <= threadCount; i++) {
        expectedList.add("" + i);
    }
    Collections.sort(resultList);
    Assert.assertEquals(expectedList, resultList);
}

@SuppressWarnings("unchecked")
private String generateInvoiceNumber() {
    InvoiceDAO invoiceDAO = new InvoiceDAO();
    Invoice invoice = ... create a valid invoice
    invoiceDAO.saveInvoice(invoice);
    log.info("generated invoice number : " + invoice.getInvoiceNumber());
    return invoice.getInvoiceNumber();
}

例如,当我在32个线程同时运行时:

代码语言:javascript
复制
@Test
public void test32() throws InterruptedException, ExecutionException {
    test(32);
}

,但是后续线程没有看到先前的事务增加了发票编号序列.

其结果是:

junit.framework.AssertionFailedError: expected:<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32>但was:<1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3>

我已经看过几次文档了,不知道为什么这不管用吗?

如果在事务中访问多个实体组,则具有XG事务的事务。如果您只访问一个,则不会访问。5 EGs的标准限制适用于所有事务。对象化事务文档

我做错什么了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-31 18:38:07

这段代码使代码不具有事务性:

最后的对象化ofy = ObjectifyService.factory().begin().cache(true); Ofy.transact(新工作){.Ofy.save().entity(设置).now(); }

因为我重用了非事务性的objectify实例。要在事务工作中获取实例,您必须始终像这样询问实例:

ObjectifyService.ofy()

更多信息在小组讨论这里

查看ObjectifyService的实现,您可以看到新的实例被推送/弹出到/从堆栈;

除此之外,测试用例仍未运行。最好的测试方法大概是同时触发http请求;

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13019565

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档