gpt4 book ai didi

google-app-engine - 如何在 AppEngine (GAE) 中进行数据库锁定?

转载 作者:太空宇宙 更新时间:2023-11-03 15:23:03 25 4
gpt4 key购买 nike

在 GAE 中,我有一个充满“一次性”的表格——诸如“最后使用的序列号”之类的东西实际上并不属于其他表格。这是一个带有字符串值对的简单字符串键。

我有一些代码可以获取一个命名整数并递增它,如下所示:

@PersistenceCapable(detachable="true")
public class OneOff
{
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
private String dataKey;

@Persistent
private String value;


public OneOff(String kk, String vv)
{
this.dataKey = kk;
this.value = vv;
}


public static OneOff persistOneOff(String kk, String vv)
{
OneOff oneoff= new OneOff(kk, vv);
PersistenceManager pm = PMF.get().getPersistenceManager();
try
{
pm.makePersistent(oneoff);
}
finally
{
pm.close();
}

return oneoff;
}


// snip...
@SuppressWarnings("unchecked")
synchronized
public static int getIntValueForKeyAndIncrement(String kk, int deFltValue)
{
int result = 0;
OneOff oneOff = null;

PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(OneOff.class);
query.setFilter("dataKey == kkParam");
query.declareParameters("String kkParam");
List<OneOff> oneOffs = (List<OneOff>) query.execute(kk);

int count = oneOffs.size();
if (count == 1)
{
oneOff = oneOffs.get(0);
result = Integer.parseInt(oneOff.value);
}
else if (count == 0)
{
oneOff = new OneOff(kk, "default");
result = deFltValue;
}
else
{
// Log WTF error.
}

// update object in DB.
oneOff.value = "" + (result+1);
try
{
pm.makePersistent(oneOff);
}
finally
{
pm.close();
}

return result;
}
// etc...

但是,当我进行这些调用时:

int val1 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val2 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val3 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);

有时我得到所需的增量,有时我得到相同的值。当我想为这个特定事务锁定数据库时,我的数据库访问似乎是异步运行的。

我以为

    synchronized
public static

应该为我做那件事,但显然不是(可能是由于多个实例在运行!)

无论如何——我如何做我想做的事? (我想在获取和更新此值时锁定我的数据库,以使整个过程是并发安全的。)

谢谢!

== 编辑 ==

我接受了罗伯特的正确答案,因为交易确实是我想要的。但是,为了完整起见,我在下面添加了更新的代码。我认为这是正确的,尽管我不确定 if(oneOff==null) 子句(try-catch 位。)

public static int getIntValueForKeyAndIncrement(String kk, int defltValue)
{
int result = 0;
Entity oneOff = null;
int retries = 3;

// Using Datastore Transactions
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
while (true)
{
com.google.appengine.api.datastore.Transaction txn = datastore.beginTransaction();
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = datastore.get (oneOffKey);
result = Integer.parseInt((String) oneOff.getProperty("value"));
oneOff.setProperty("value", "" + (result+1));
datastore.put(oneOff);
txn.commit();
break;
}
catch (EntityNotFoundException ex)
{
result = defltValue;
}
catch (ConcurrentModificationException ex)
{
if (--retries < 0)
{
throw ex;
}
}

if (oneOff == null)
{
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = new Entity(oneOffKey);
oneOff.setProperty("value", "" + (defltValue+1));
datastore.put(txn, oneOff);
datastore.put(oneOff);
txn.commit();
break;
}
finally
{
if (txn.isActive())
{
txn.rollback();
}
}
}
else
{
if (txn.isActive())
{
txn.rollback();
}
}
}
return result;
}

最佳答案

您应该在 transaction 中更新您的值.只要您的读取和写入在单个事务中,App Engine 的事务就会防止两个更新相互覆盖。一定要关注实体组的讨论。

关于google-app-engine - 如何在 AppEngine (GAE) 中进行数据库锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6963510/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com