我认为我的问题类似于:BulkLoader -export_transform或https://stackoverflow.com/questions/3220911/gae-datastore-export-transform
基本上,我使用bulkloader 来备份和恢复我创建的实体。为了测试,我使用了“游戏”类型并将其输出到名为 game.csv 的 csv 文件中。
这是我经历的过程:
使用以下命令将游戏类型下载到 game.csv:
appcfg.py download_data --config_file=bulkloader.yaml --kind=Game --filename=game.csv --application=MyAppId --url= http://MyAppId.appspot.com/remote_api --rps_limit=500 --带宽限制=2500000 --batch_size=100
删除所有游戏实体。然后我检查了我的应用程序的管理门户数据存储查看器选项卡,我发现我的数据存储中没有更多实体。
使用使用创建的 game.csv 上传游戏类型(命令与download_data相同,但使用upload_data):
appcfg.py upload_data --config_file=bulkloader.yaml --kind=Game --filename=game.csv --application=MyAppId --url= http://MyAppId.appspot.com/remote_api --rps_limit=500 --带宽限制=2500000 --batch_size=100
运行一个通过“名称”检索实体的 servlet(这是下面 Game.java 中显示的属性)。
出现以下错误:
Uncaught exception from servlet
java.lang.IllegalStateException: Loaded Entity has name but com.example.app.model.Game has no String @Id
at com.googlecode.objectify.impl.ConcreteEntityMetadata.setKey(ConcreteEntityMetadata.java:343)
at com.googlecode.objectify.impl.ConcreteEntityMetadata.toObject(ConcreteEntityMetadata.java:210)
at com.googlecode.objectify.impl.QueryImpl$ToObjectIterator.translate(QueryImpl.java:640)
at com.googlecode.objectify.impl.QueryImpl$ToObjectIterator.translate(QueryImpl.java:629)
at com.googlecode.objectify.util.TranslatingIterator.next(TranslatingIterator.java:35)
at com.googlecode.objectify.impl.QueryImpl.list(QueryImpl.java:470)
我怀疑这与我的bulkloader.yaml文件没有为__key__
属性配置正确有关。所以我把它贴在下面:
- import: google.appengine.ext.bulkload.transform
- import: google.appengine.ext.bulkload.bulkloader_wizard
- import: google.appengine.ext.db
- import: google.appengine.api.datastore
- import: google.appengine.api.users
transformers:
- kind: Game
connector: csv
connector_options:
# TODO: Add connector options here--these are specific to each connector.
property_map:
- property: __key__
external_name: key
export_transform: transform.key_id_or_name_as_string
- property: __scatter__
#external_name: __scatter__
# Type: ShortBlob Stats: 56 properties of this type in this kind.
- property: genre
external_name: genre
# Type: String Stats: 6639 properties of this type in this kind.
- property: name
external_name: name
# Type: String Stats: 6639 properties of this type in this kind.
- property: releasedate
external_name: releasedate
# Type: Date/Time Stats: 6548 properties of this type in this kind.
import_transform: transform.import_date_time('%Y-%m-%dT%H:%M:%S')
export_transform: transform.export_date_time('%Y-%m-%dT%H:%M:%S')
在删除和上传数据之前,“游戏”类型(在应用程序管理门户的数据存储查看器选项卡中)显示ID/NAME
带有超链接的列,看起来像ID=12345,ID=67890 ... 对于每个实体行。
上传后,datastre 查看器会显示带有超链接的ID/NAME
列,这些超链接看起来像NAME=12345,NAME=67890 ... 对于每个实体行。
可能的原因?
我实际上已经在https://groups.google.com/forum/?hl=en#!topic/objectify-appengine/FFuB2Onfnzc上发布了我的问题,但我们不知道避免在何时将__key__
属性转换为字符串的语法上传回数据。
Jeff(Objectify3.0 的创建者)说:
错误消息表明数据存储区中的数据为字符串名称键,但您的游戏实体具有数字长 @Id。我真的不知道批量加载程序的语法,但最可疑的行是这一行:
export_transform: transform.key_id_or_name_as_string
看起来您在这里将所有数字 id 转换为字符串,这将是您的问题。将它们保留为数字。
我试过删除,export_transform: transform.key_id_or_name_as_string
但是当我下载时,csv文件是空的。
也许一个解决方案是避免使用--config_file
参数和bulkloader.yaml文件,只让 bulkloader 下载/上传数据而不进行任何转换?
额外信息,以防可能相关
我正在使用 objectify3.0.jar 来操作我的 GAE 数据存储。所以我的游戏类型看起来像这样:
public class Game {
@Id private Long id; //This is my key property, auto generated by objectify
private String name;
private String genre;
private Date releasedate;
//ommitting getters and setters
}