Java Google Appengine无事务切分计数器
我将介绍Java中的切分计数器示例: 我对增量方法的实现有一个问题。在python中,它在事务中显式地包装get()和增量。在Java示例中,它只是检索并设置它。我不确定我是否完全理解数据存储和事务,但似乎关键更新部分应该包装在数据存储事务中。我错过什么了吗 原始代码: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
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);