【问题标题】:How to get list of internal entities?如何获取内部实体列表?
【发布时间】:2016-07-20 06:28:19
【问题描述】:

我有两个类 - Employee 和 Job - 作为域

public class Employee {
   private Long id;
   private String name;
   private List<Job> jobList = new ArrayList<>();
   private Week week;

   public Employee() {
   }

   public Employee(String name) {
       this.name = name;
       jobList.add(new Job("Haircut", 30, 300));
       week = Week.init();
   }
//Getters and setters for all fields.
}

public class Job {
    private Long id;
    private String title;
    private int duration;
    private int price;

    public Job() {
    }

    public Job(String title, int duration, int price) {
        this.duration = duration;
        this.price = price;
        this.title = title;
    }
//Getters and setters for all fields.
}

作为后端

@Entity
public class Employee {
    @Id
    private Long id;
    private String name;
    private List<Job> jobList = new ArrayList<>();
    private Week week;

    public Employee() {
    }
    //Getters and setters for all fields.
}

@Entity
public class Job {
    @Id
    private Long id;
    private String title;
    private int duration;
    private int price;

    public Job() {
    }
    //Getters and setters for all fields.
}

在 OfyService 中注册

public class OfyService {

    static {
        factory().register(Employee.class);
        factory().register(Job.class);
    }

    public static Objectify ofy() {
        return ObjectifyService.ofy();
    }

    public static ObjectifyFactory factory() {
        return ObjectifyService.factory();
    }
}

在我的 EmployeeEndpoint 中有两种方法:

@ApiMethod(
    name = "list",
    path = "employee",
    httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<Employee> list(@Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {
    limit = limit == null ? DEFAULT_LIST_LIMIT : limit;
    Query<Employee> query = OfyService.ofy().load().type(Employee.class).limit(limit);
    if (cursor != null) {
        query = query.startAt(Cursor.fromWebSafeString(cursor));
    }
    QueryResultIterator<Employee> queryIterator = query.iterator();
    List<Employee> employeeList = new ArrayList<Employee>(limit);
    while (queryIterator.hasNext()) {
        employeeList.add(queryIterator.next());
    }
    return CollectionResponse.<Employee>builder().setItems(employeeList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}

@ApiMethod(
    name = "jobList",
    path = "employee/{id}/jobList",
    httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<Job> jobList(@Named("id") Long employeeId) {
    int limit = DEFAULT_LIST_LIMIT;
    Query<Job> query = OfyService.ofy().load().type(Job.class).limit(limit);
    QueryResultIterator<Job> queryIterator = query.iterator();
    List<Job> jobList = new ArrayList<>(limit);
    while (queryIterator.hasNext()) {
        jobList.add(queryIterator.next());
    }
    return CollectionResponse.<Job>builder().setItems(jobList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}

我可以使用 list() 方法在服务器上看到员工,并且员工内部列出了一个职位:

200

{
    "items": [
   {
   "id": "5732568548769792",
   "name": "Sophie",
   "jobList": [
      {
       "title": "Haircut",
       "duration": 30,
       "price": 300
      }
   ],
...
}

但是当我尝试通过 id = 5732568548769792 的 jobList() 方法获取此 Job 时,它什么也不返回:

200

{
 "kind": "employeeApi#resourcesItem",
 "etag": "\"eEm63BNCBzxEAy3aqxetQdspGKA/FzFIL_vxOIIBu5chWZYooI-ArvQ\""
}

如果我指定祖先

Query<Job> query = OfyService.ofy().load().type(Job.class).ancestor(Key.create(Employee.class, employeeId)).limit(limit);

jobList()中结果没有改变。

我应该在上面的代码中进行哪些更改以获得所需的工作列表?

【问题讨论】:

    标签: android google-app-engine google-cloud-endpoints objectify google-cloud-datastore


    【解决方案1】:

    根据您的实体模型,Employee 和 Job 实体之间没有关系。因此无法对 Job 实体执行祖先查询,因为它没有任何祖先(父)。

    此外,Employee 实体具有 joblist 属性。这意味着您可以在使用employee.getjobList() Employee Entity中jobList的getter方法获取该员工后获取该员工的工作列表。

    更好的方法是更改​​实体模型并在 Employee 和 Job 之间创建关系,然后使用 Web 安全密钥获取实体,例如

    变化:

    @Entity
    public class Employee {
        @Id
        private Long id;
        private String name;
        private List<Job> jobList = new ArrayList<>();
        private Week week;
    
        public Employee() {
        }
    
        //Getters and setters for all fields.
    }
    
    @Entity
    public class Job {
        @Id
        private Long id;
        private String title;
        private int duration;
        private int price;
    
        public Job() {
        }
        //Getters and setters for all fields.
    }
    

    收件人:

    @Entity
    public class Employee {
        @Id
        private Long id;
        private String name;
    
        private Week week;
    
        public Employee() {
        }
    public String getWebsafeKey() {
            return Key.create(Employee.class, id).getString();
        }
        //Getters and setters for all fields.
    }
    
    @Entity
    public class Job {
        @Id
        private Long id;
        private String title;
        private int duration;
        private int price;
    @Index
        @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
        Ref<Employee> employeeRef;
        public Job() {
        }
     public String getWebsafeKey() {
            return Key.create(employeeRef.getKey(), Job.class, id).getString();
        }
        //Getters and setters for all fields.
    }
    

    此模型会返回您创建的实体的网络安全密钥作为响应。每当您想访问创建的实体时,请使用此网络安全。 当您创建工作时,创建要创建的工作与已使用以下方法创建的 Employee 的关系:

     job.employeeRef = Ref.create(employeeKey);
    

    之后更改您的 Api 方法:

    @ApiMethod(
        name = "jobList",
        path = "employee/{id}/jobList",
        httpMethod = ApiMethod.HttpMethod.GET)
    public CollectionResponse<Job> jobList(@Named("id") Long employeeId) {
        int limit = DEFAULT_LIST_LIMIT;
        Query<Job> query = OfyService.ofy().load().type(Job.class).limit(limit);
        QueryResultIterator<Job> queryIterator = query.iterator();
        List<Job> jobList = new ArrayList<>(limit);
        while (queryIterator.hasNext()) {
            jobList.add(queryIterator.next());
        }
        return CollectionResponse.<Job>builder().setItems(jobList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
    }
    

    收件人:

    @ApiMethod(
        name = "jobList",
        path = "employee/{employee_web_safe_key}/jobList",
        httpMethod = ApiMethod.HttpMethod.GET)
    public CollectionResponse<Job> jobList(@Named("employee_web_safe_key") String employeeWSKey) {
        int limit = DEFAULT_LIST_LIMIT;
        Query<Job> query = OfyService.ofy().load().type(Job.class).limit(limit);
    query=query.filter("employeeRef =",Key.create(employeeWSKey))
        QueryResultIterator<Job> queryIterator = query.iterator();
        List<Job> jobList = new ArrayList<>(limit);
        while (queryIterator.hasNext()) {
            jobList.add(queryIterator.next());
        }
        return CollectionResponse.<Job>builder().setItems(jobList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
    }
    

    这将为您提供与给定员工相关的所有工作。

    如果您通过在 RefemployeeRef 上添加 @Parent 索引来创建模型,您也可以执行祖先查询; 例如

    @Parent
    @Index
    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
    Ref<Employee> employeeRef;
    

    【讨论】:

    • 谢谢,Baqir。不幸的是,我现在没有时间检查您的答案,但我一定会这样做。
    • 没关系@isabent,我能理解。在您检查您是否会发现答案有帮助时,请提出我。 :)
    猜你喜欢
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    相关资源
    最近更新 更多