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 如何在名称空间之间复制数据存储实体_Java_Google App Engine - Fatal编程技术网

Java 如何在名称空间之间复制数据存储实体

Java 如何在名称空间之间复制数据存储实体,java,google-app-engine,Java,Google App Engine,我想将一个名称空间(比如www.mysite.com)中的所有数据复制到另一个名称空间(比如nightly.latest.mysite.appspot.com)。最好的方法是什么 示例名称空间不是随机的:它们是由为应用程序提供服务的给定域的名称空间筛选器设置的名称空间 我希望能够将所有“生产”数据拉入“非生产”名称空间进行测试。不幸的是,目前还没有自动化的方法 您必须循环所有数据并将其重新保存到新名称空间。您可以在文档中阅读Java和名称空间。名称空间是键的一部分。因此,您无法将所有数据从一个命

我想将一个名称空间(比如www.mysite.com)中的所有数据复制到另一个名称空间(比如nightly.latest.mysite.appspot.com)。最好的方法是什么

示例名称空间不是随机的:它们是由为应用程序提供服务的给定域的名称空间筛选器设置的名称空间


我希望能够将所有“生产”数据拉入“非生产”名称空间进行测试。

不幸的是,目前还没有自动化的方法


您必须循环所有数据并将其重新保存到新名称空间。您可以在文档中阅读Java和名称空间。

名称空间是键的一部分。因此,您无法将所有数据从一个命名空间更改或复制到另一个命名空间。据我所知,您所能做的就是从一个名称空间中获取所有对象,并在另一个名称空间中创建具有相同属性的新对象。

我正在使用它。我不会详细介绍如何设置它。您可以阅读该信息

现在,您必须输入要复制的每个类名。TODO正在研究如何以编程方式循环所有结果,这样就不必单独指定每个种类/类

import java.util.logging.Logger;

import org.apache.hadoop.io.NullWritable;

import com.google.appengine.api.NamespaceManager;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.tools.mapreduce.AppEngineMapper;

public class DatastoreCopyMapper extends
        AppEngineMapper<Key, Entity, NullWritable, NullWritable> {

    private static final Logger log = Logger
            .getLogger(DatastoreCopyMapper.class.getName());
    private static String destination;

    public DatastoreCopyMapper() {
    }

    @Override
    public void taskSetup(Context context) {
        log.warning("Doing per-task setup");
        destination = context.getConfiguration().get("destination");
        log.warning("destination: " + destination);
    }

    @Override
    public void map(Key key, Entity value, Context context) {

        NamespaceManager.set(destination);
        String name = key.getName();
        long id = key.getId();
        Key destinationKey = null;
        if (name != null) {
            destinationKey = KeyFactory.createKey(key.getKind(), name);
        } else if (id != 0) {
            destinationKey = KeyFactory.createKey(key.getKind(), id);
        }
        Entity destinationEntity = new Entity(destinationKey);
        destinationEntity.setPropertiesFrom(value);
        DatastoreService datastore = DatastoreServiceFactory
                .getDatastoreService();

        datastore.put(destinationEntity);

    }
}
import java.util.logging.Logger;
导入org.apache.hadoop.io.NullWritable;
导入com.google.appengine.api.NamespaceManager;
导入com.google.appengine.api.datastore.DatastoreService;
导入com.google.appengine.api.datastore.DatastoreServiceFactory;
导入com.google.appengine.api.datastore.Entity;
导入com.google.appengine.api.datastore.Key;
导入com.google.appengine.api.datastore.KeyFactory;
导入com.google.appengine.tools.mapreduce.AppEngineMapper;
公共类DatastoreCopyMapper扩展
AppEngineMapper{
专用静态最终记录器日志=记录器
.getLogger(DatastoreCopyMapper.class.getName());
私有静态字符串目的地;
公共数据存储CopyMapper(){
}
@凌驾
公共void任务设置(上下文){
日志警告(“按任务执行设置”);
destination=context.getConfiguration().get(“destination”);
日志警告(“目的地:+目的地”);
}
@凌驾
公共无效映射(键、实体值、上下文){
NamespaceManager.set(目的地);
字符串名称=key.getName();
long id=key.getId();
Key destinationKey=null;
if(name!=null){
destinationKey=KeyFactory.createKey(key.getKind(),name);
}如果(id!=0),则为else{
destinationKey=KeyFactory.createKey(key.getKind(),id);
}
实体destinationEntity=新实体(destinationKey);
destinationEntity.setPropertiesFrom(值);
DatastoreService数据存储=DatastoreServiceFactory
.getDatastoreService();
datastore.put(目的性);
}
}
mapreduce.xml

<configurations>
  <configuration name="Copy between namespaces">
    <property>
      <name>mapreduce.map.class</name>
      <value>com.mysite.server.DatastoreCopyMapper</value>
    </property>
    <property>
      <name>mapreduce.inputformat.class</name>
      <value>com.google.appengine.tools.mapreduce.DatastoreInputFormat</value>
    </property>
    <property>
      <name human="Entity Kind to Map Over">mapreduce.mapper.inputformat.datastoreinputformat.entitykind</name>
      <value template="optional">User</value>
    </property>

    <property>
      <name human="Destination Namespace">mapreduce.mapper.inputformat.datastoreinputformat.destination</name>
      <value template="optional">dev.mysite.com</value>
    </property>

  </configuration>
</configurations>

mapreduce.map.class
com.mysite.server.DatastoreCopyMapper
mapreduce.inputformat.class
com.google.appengine.tools.mapreduce.DatastoreInputFormat
mapreduce.mapper.inputformat.datastoreinputformat.entitykind
使用者
mapreduce.mapper.inputformat.datastoreinputformat.destination
dev.mysite.com

您认为远程访问API可以帮助您完成这项工作吗?它要求您下载python SDK,但您可以将其设置为适用于java应用程序。昨天我碰巧读了《谷歌应用程序引擎编程》中关于批量数据操作和远程访问的这一章:是的,我的假设是必须使用远程api及其批量数据操作,我只是不知道如何,也不想重新发明轮子。如果你想采用批量加载方法,您还需要上传应用程序的Python实例。文档在这里:@Robert我真的需要上传python sdk吗?“提示:如果您有Java应用程序,您可以通过安装Java运行时环境中包含的远程api处理程序的Java版本来使用Python appcfg.py工具。处理程序servlet类为com.google.apphosting.utils.remoteapi.RemoteApiServlet。”对此表示抱歉。您不再需要上传Python版本。但是您仍然在客户端使用Python工具。如果您在名称空间之间的同一个应用程序中执行此操作,您可能需要考虑我对该问题的答案。这将避免下载然后重新上传所有数据(可能会快得多)。我确信这种方法会出现超时问题,所以这不是小事,这让我很犹豫是否要走这条路。您需要使用查询游标和任务队列,就像应用程序引擎上的许多其他任务一样。是的。这开始感觉像是一个成熟的项目。我想我会尝试使用mapreduce api来实现这一点。当我今天通过谷歌搜索发现这个问题时,我想说,8年后的今天,似乎仍然没有一种自动化的方式,但是您应该能够使用googledataflow/ApacheBeam加载名称空间的所有实体,获取它们的构建器,替换密钥(或仅替换名称空间)并重新保存它们,而不需要使用taskQueues等。