6

您好有两个相关的实体:客户和汽车。每个客户可以拥有几辆汽车

这是实体的汇总视图:

public class Customer 
{
    //Inner classes for partial loads
    public static class NoCars{}

    @Id protected String id;
    private String fullName;
    @Load(unless=NoCars.class) private List<Ref<Car>> cars;
}

public class Car
{
    @Id private Long id;
    private String makeAndModel;
    private String plateNumber;
}

这是一种从数据存储区和他拥有的所有汽车中检索客户的方法:

public Customer getCustomer(@Named("id") String customerId)
{
    Customer customer =  ofy().load().type(Customer.class).id(customerId).now();
    if (customer==null)
        throw new NotFoundException("customer not found");
    else
        return customer;
}

endpoints.sh 无法实现这一点,因为不支持List <Ref<Car>>返回类型Customer中包含的类型,但我发现了这个有趣的解决方法:

我创建了CustomerPOJO类

public class CustomerPOJO
{
    private String fullName;
}

并修改了类Customer以从它扩展

public class Customer extends CustomerPOJO
{
    //Inner classes for partial loads
    public static class NoCars{}

    @Id protected String id;
    @Load(unless=NoCars.class) private List<Ref<Car>> cars = new ArrayList<>();
}

和getter方法是:

public CustomerPOJO getCustomer(@Named("id") String customerId)
{
    Customer customer =  ofy().load().type(Customer.class).id(customerId).now();
    if (customer==null)
        throw new NotFoundException("customer not found");
    else
        return customer;
}

请注意,该方法声明CustomerPOJO为返回类型,但它实际上返回一个“完整” Customer

这适用于 AppEngine 1.8.0 + Objectify 4.0 RC2。它在一次调用中获取客户数据和他拥有的所有汽车及其属性(makeAndModel和)。plateNumber

升级到 1.8.9 后出现问题。endpoints.sh 仍然有效,因为返回类型完全兼容,但是在将 Customer objecto 解析为 JSON 时,我在运行时遇到异常。

java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: 直接自引用导致循环(通过引用链:entity.Customer["cars"]->java.util. ArrayList[0]->com.googlecode.objectify.impl.ref.LiveRef["key"]->com.googlecode.objectify.Key["root"])

任何其他适用于 1.8.9 的解决方法?@ApiTransformer 是唯一的选择吗?

4

1 回答 1

3

解决方案非常简单......只需隐藏 Ref 字段。它现在确实为 API 使用者提供了任何价值,它只会给解析器带来麻烦:

我将List<Ref<Car>>getter 和 setter 替换为:

public List<Car> getCars()
{
    List<Car> ret = new ArrayList<>();
    Iterator<Ref<Car>> it = cars.iterator();

    while (it.hasNext())
        ret.add(it.next().getValue());
    return ret;
}

public void setCars(List<Car> newCars)
{
    Iterator<Car> it = newCars.iterator();

    while (it.hasNext())
        addCar(it.next());
}

就这样

于 2014-02-07T12:38:14.927 回答