Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Google Appengine无事务切分计数器_Java_Google App Engine_Transactions_Concurrency - Fatal编程技术网

Java Google Appengine无事务切分计数器

Java Google Appengine无事务切分计数器,java,google-app-engine,transactions,concurrency,Java,Google App Engine,Transactions,Concurrency,我将介绍Java中的切分计数器示例: 我对增量方法的实现有一个问题。在python中,它在事务中显式地包装get()和增量。在Java示例中,它只是检索并设置它。我不确定我是否完全理解数据存储和事务,但似乎关键更新部分应该包装在数据存储事务中。我错过什么了吗 原始代码: public void increment() { PersistenceManager pm = PMF.get().getPersistenceManager(); Random generator

我将介绍Java中的切分计数器示例:

我对增量方法的实现有一个问题。在python中,它在事务中显式地包装get()和增量。在Java示例中,它只是检索并设置它。我不确定我是否完全理解数据存储和事务,但似乎关键更新部分应该包装在数据存储事务中。我错过什么了吗

原始代码:

  public void increment() {
    PersistenceManager pm = PMF.get().getPersistenceManager();

    Random generator = new Random();
    int shardNum = generator.nextInt(NUM_SHARDS);

    try {
      Query shardQuery = pm.newQuery(SimpleCounterShard.class);
      shardQuery.setFilter("shardNumber == numParam");
      shardQuery.declareParameters("int numParam");

      List<SimpleCounterShard> shards =
          (List<SimpleCounterShard>) shardQuery.execute(shardNum);
      SimpleCounterShard shard;

      // If the shard with the passed shard number exists, increment its count
      // by 1. Otherwise, create a new shard object, set its count to 1, and
      // persist it.
      if (shards != null && !shards.isEmpty()) {
        shard = shards.get(0);
        shard.setCount(shard.getCount() + 1);
      } else {
        shard = new SimpleCounterShard();
        shard.setShardNumber(shardNum);
        shard.setCount(1);
      }

      pm.makePersistent(shard);
    } finally {
      pm.close();
    }
  }
}
public void increment(){
PersistenceManager pm=PMF.get().getPersistenceManager();
随机生成器=新随机();
int shardNum=generator.nextInt(NUM_SHARDS);
试一试{
Query shardQuery=pm.newQuery(SimpleCounterShard.class);
setFilter(“shardNumber==numParam”);
shardQuery.declareParameters(“int numParam”);
列出碎片=
(List)shardQuery.execute(shardNum);
简单计数器硬碎片;
//如果具有传递的碎片编号的碎片存在,则增加其计数
//否则,创建一个新的碎片对象,将其计数设置为1,然后
//坚持下去。
if(shards!=null&&!shards.isEmpty()){
shard=shard.get(0);
shard.setCount(shard.getCount()+1);
}否则{
shard=新的SimpleCounterShard();
shard.setShardNumber(shardNum);
shard.setCount(1);
}
pm.makePersistent(shard);
}最后{
pm.close();
}
}
}
事务代码(我相信您需要在事务中运行此代码,以确保并发事务下的正确性?)

public void increment(){
PersistenceManager pm=PMF.get().getPersistenceManager();
随机生成器=新随机();
int shardNum=generator.nextInt(NUM_SHARDS);
试试{
Query shardQuery=pm.newQuery(SimpleCounterShard.class);
setFilter(“shardNumber==numParam”);
shardQuery.declareParameters(“int numParam”);
列表碎片=
(List)shardQuery.execute(shardNum);
简单计数器硬碎片;
//如果具有传递的碎片编号的碎片存在,则增加其计数
//否则,创建一个新的碎片对象,将其计数设置为1,然后
//坚持下去。
如果(shards!=null&&!shards.isEmpty()){
事务tx=pm.currentTransaction();
试试{
tx.begin();
//我相信事务对象需要按ID加载(不能使用外部查询的实体)
Key shardKey=KeyFactory.Builder(SimpleCounterShard.class.getSimpleName(),shards.get(0.getID())
shard=pm.getObjectById(SimpleCounterShard.class,shardKey);
shard.setCount(shard.getCount()+1);
tx.commit();
}最后{
如果(tx.isActive()){
tx.回滚();
} 
} 
}否则{
shard=新的SimpleCounterShard();
shard.setShardNumber(shardNum);
shard.setCount(1);
} 
pm.makePersistent(shard);
}最后{
pm.close();
} 
} 

本节直接从文档中看出,您需要交易的想法完全正确:

此示例演示了事务的一种用法:使用相对于其当前值的新属性值更新实体

这需要一个事务,因为该代码获取对象后,另一个用户可能会在保存修改后的对象之前更新该值。如果没有事务,用户的请求将在另一个用户更新之前使用counter的值,保存操作将覆盖新值。在事务中,应用程序被告知其他用户的更新。如果在事务期间更新了实体,则事务将失败并出现异常。应用程序可以重复事务以使用新数据


它与切分示例的功能非常接近,与您一样,我无法找到切分计数器不同的任何原因。

我在Appengine问题跟踪程序上创建了一个开放问题:@Dougnukem-极好。如果可以的话,我会再次投票支持你的问题,因为我努力为项目提供反馈以改进它。我把你的另一个问题改为:——)
public void increment() { 
    PersistenceManager pm = PMF.get().getPersistenceManager(); 
    Random generator = new Random(); 
    int shardNum = generator.nextInt(NUM_SHARDS); 
    try { 
      Query shardQuery = pm.newQuery(SimpleCounterShard.class); 
      shardQuery.setFilter("shardNumber == numParam"); 
      shardQuery.declareParameters("int numParam"); 
      List<SimpleCounterShard> shards = 
          (List<SimpleCounterShard>) shardQuery.execute(shardNum); 
      SimpleCounterShard shard; 
      // If the shard with the passed shard number exists, increment its count 
      // by 1. Otherwise, create a new shard object, set its count to 1, and 
      // persist it. 
      if (shards != null && !shards.isEmpty()) { 
            Transaction tx = pm.currentTransaction(); 
        try { 
            tx.begin(); 
            //I believe in a transaction objects need to be loaded by ID (can't use the outside queried entity) 
             Key shardKey = KeyFactory.Builder(SimpleCounterShard.class.getSimpleName(), shards.get(0).getID()) 
            shard =  pm.getObjectById(SimpleCounterShard.class, shardKey); 
            shard.setCount(shard.getCount() + 1); 
            tx.commit(); 
        } finally { 
            if (tx.isActive()) { 
                tx.rollback(); 
            } 
        } 
      } else { 
        shard = new SimpleCounterShard(); 
        shard.setShardNumber(shardNum); 
        shard.setCount(1); 
      } 
      pm.makePersistent(shard); 
    } finally { 
      pm.close(); 
    } 
  } 
    Key k = KeyFactory.createKey("Employee", "k12345");
    Employee e = pm.getObjectById(Employee.class, k);
    e.counter += 1;
    pm.makePersistent(e);