Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.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
为什么Google数据存储控制台的行为与GAE Java数据存储库不同?_Java_Google App Engine_Google Cloud Datastore - Fatal编程技术网

为什么Google数据存储控制台的行为与GAE Java数据存储库不同?

为什么Google数据存储控制台的行为与GAE Java数据存储库不同?,java,google-app-engine,google-cloud-datastore,Java,Google App Engine,Google Cloud Datastore,我有一个GoogleAppEngine+Java应用程序,它已经愉快地运行了很多年(使用JDO+数据存储进行持久化),我在手动更新GoogleDataStore控制台中实体的属性方面没有问题(偶尔也不情愿) 最近(可能是最近2-3个月),我注意到一个行为上的变化,它破坏了我们的应用程序。我不知道到底出了什么问题,也不知道我们如何处理 所以我的问题是: 为什么它的表现不同?我能做些什么 让我首先尝试解释我看到的行为,然后展示我的最小可能的复制测试用例 假设您有一个简单的持久性类: @Persist

我有一个GoogleAppEngine+Java应用程序,它已经愉快地运行了很多年(使用JDO+数据存储进行持久化),我在手动更新GoogleDataStore控制台中实体的属性方面没有问题(偶尔也不情愿)

最近(可能是最近2-3个月),我注意到一个行为上的变化,它破坏了我们的应用程序。我不知道到底出了什么问题,也不知道我们如何处理

所以我的问题是: 为什么它的表现不同?我能做些什么

让我首先尝试解释我看到的行为,然后展示我的最小可能的复制测试用例

假设您有一个简单的持久性类:

@PersistenceCapable
public class Account implements Serializable {

@Persistent private ShortBlob testShortBlob;
@Persistent private String name;
// ...etc...

}
如果我过去通过DataStoreWeb控制台编辑名称,它将按预期工作,名称字段将更改,其他一切都将正常工作

我现在看到的行为是,通过控制台保存实体后,我无法再在JDO中查询和加载实体,我得到:

java.lang.ClassCastException: com.google.appengine.api.datastore.Blob cannot be cast to com.google.appengine.api.datastore.ShortBlob
它指向一些底层数据存储更改,这意味着ShortBlob字段的类型正在从ShortBlob更改为Blob(即使我没有通过控制台对该字段进行编辑)

此测试用例将复制该问题:

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
// this one really is a ShortBlob - will load fine in JDO
Entity account = new Entity("Account", "123");
account.setProperty("name", "Test Name");
account.setUnindexedProperty("testShortBlob", new ShortBlob("blah".getBytes()));

datastore.put(account);
// this one really is not a ShortBlob, its a blob - it will fail for the same reason I am seeing in production.
account = new Entity("Account", "124");
account.setProperty("name", "Test Name 2");
account.setUnindexedProperty("testShortBlob", new Blob("blah".getBytes()));
datastore.put(account);

// then load the entity via JDO

 try {
    accountFromJdo = pm.getObjectById(Account.class, key);
  } catch (Exception ex) {
    System.out.println("We get here, the object won't load with the ClassCast Exception");
  }
这就是问题所在,但为什么通过云数据存储控制台进行保存会将ShortBlob更改为Blob

我目前的解决方法是在数据存储控制台中将ShortBlob字段设置为null,这样就可以加载实体。但如果blob中的数据很重要,那就糟了

更新:

我在这方面做了更多的测试,使用低级别的JSON API,看看在通过控制台保存实体之前和之后,是否可以在原始JSON响应中发现差异。好消息是,我可以

在通过控制台编辑实体之前,通过JDO App Engine界面保存到数据存储的shortBlob字段如下所示:

        },
        "testShortBlob": {
          "blobValue": "tNp7MfsjhdfjkahsdvfkjhsdvfIItWyzy6glmIrow4WWhRPbhQ/U+MGX3opVvpxu"
        },
但是,如果我进入数据存储控制台,编辑实体(保持blob字段不变,编辑一个不相关的字段,例如name。现在,当我运行相同的查询时,我得到:

        },
        "testShortBlob": {
          "blobValue": "tNp7MfsjhdfjkahsdvfkjhsdvfIItWyzy6glmIrow4WWhRPbhQ/U+MGX3opVvpxu",
          "excludeFromIndexes": true
        },
细微的差别,但我认为这很重要,根据
ShortBlob
索引,而
Blob
不索引


因此,我想我现在的问题是:为什么通过云数据存储控制台编辑实体会改变blob字段的索引状态?

感谢您提出的详细问题和调试。这似乎有点可疑。我将确保分配给正确的团队

就解决办法而言:

您注意到的JSON API提供了多种帮助,使其易于访问


可以使用该API以事务方式读取/修改/写入实体。在您的情况下,它将允许您执行所需的转换。或者,通过JDO进行修改也可以工作。

我认为这是一个错误,数据存储控制台在保存时不应更改属性的索引状态,因此我提出了一个问题在这里的跟踪器中:这个错误已经被修复,同时我发现我能够使用数据存储API(而不是JDO API)修复损坏的实体,方法是使用blob中的字节将值设置回ShortBlob,比如:.setProperty(prop,new ShortBlob((blob)value).getBytes());