如何在 android 中具有一对一或一对多关系的对象化实体中插入记录
how to insert record in objectify entity having one-to-one or one-to-many relationship in android
我有如下 class 城市的模型:
@Entity
public class City {
@Id
Long id;
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
我有另一个模型class下面给出的人:
@Entity
public class Person {
@Id
Long id;
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
Key<City> city;
}
之后,我使用 android studio 为 class 生成端点并进行部署。
这里是生成端点的代码:
PersonEndpoint
@Api(
name = "personApi",
version = "v1",
resource = "person",
namespace = @ApiNamespace(
ownerDomain = "backend.faceattendence.morpho.com",
ownerName = "backend.faceattendence.morpho.com",
packagePath = ""
)
)
public class PersonEndpoint {
private static final Logger logger = Logger.getLogger(PersonEndpoint.class.getName());
private static final int DEFAULT_LIST_LIMIT = 20;
static {
// Typically you would register this inside an OfyServive wrapper. See: https://code.google.com/p/objectify-appengine/wiki/BestPractices
ObjectifyService.register(Person.class);
}
/**
* Returns the {@link Person} with the corresponding ID.
*
* @param id the ID of the entity to be retrieved
* @return the entity with the corresponding ID
* @throws NotFoundException if there is no {@code Person} with the provided ID.
*/
@ApiMethod(
name = "get",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.GET)
public Person get(@Named("id") Long id) throws NotFoundException {
logger.info("Getting Person with ID: " + id);
Person person = ofy().load().type(Person.class).id(id).now();
if (person == null) {
throw new NotFoundException("Could not find Person with ID: " + id);
}
return person;
}
/**
* Inserts a new {@code Person}.
*/
@ApiMethod(
name = "insert",
path = "person",
httpMethod = ApiMethod.HttpMethod.POST)
public Person insert(Person person) {
// Typically in a RESTful API a POST does not have a known ID (assuming the ID is used in the resource path).
// You should validate that person.id has not been set. If the ID type is not supported by the
// Objectify ID generator, e.g. long or String, then you should generate the unique ID yourself prior to saving.
//
// If your client provides the ID then you should probably use PUT instead.
ofy().save().entity(person).now();
logger.info("Created Person.");
return ofy().load().entity(person).now();
}
/**
* Updates an existing {@code Person}.
*
* @param id the ID of the entity to be updated
* @param person the desired state of the entity
* @return the updated version of the entity
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code Person}
*/
@ApiMethod(
name = "update",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.PUT)
public Person update(@Named("id") Long id, Person person) throws NotFoundException {
// TODO: You should validate your ID parameter against your resource's ID here.
checkExists(id);
ofy().save().entity(person).now();
logger.info("Updated Person: " + person);
return ofy().load().entity(person).now();
}
/**
* Deletes the specified {@code Person}.
*
* @param id the ID of the entity to delete
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code Person}
*/
@ApiMethod(
name = "remove",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("id") Long id) throws NotFoundException {
checkExists(id);
ofy().delete().type(Person.class).id(id).now();
logger.info("Deleted Person with ID: " + id);
}
/**
* List all entities.
*
* @param cursor used for pagination to determine which page to return
* @param limit the maximum number of entries to return
* @return a response that encapsulates the result list and the next page token/cursor
*/
@ApiMethod(
name = "list",
path = "person",
httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<Person> list(@Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {
limit = limit == null ? DEFAULT_LIST_LIMIT : limit;
Query<Person> query = ofy().load().type(Person.class).limit(limit);
if (cursor != null) {
query = query.startAt(Cursor.fromWebSafeString(cursor));
}
QueryResultIterator<Person> queryIterator = query.iterator();
List<Person> personList = new ArrayList<Person>(limit);
while (queryIterator.hasNext()) {
personList.add(queryIterator.next());
}
return CollectionResponse.<Person>builder().setItems(personList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}
private void checkExists(Long id) throws NotFoundException {
try {
ofy().load().type(Person.class).id(id).safe();
} catch (com.googlecode.objectify.NotFoundException e) {
throw new NotFoundException("Could not find Person with ID: " + id);
}
}
}
城市端点
@Api(
name = "cityApi",
version = "v1",
resource = "city",
namespace = @ApiNamespace(
ownerDomain = "backend.faceattendence.morpho.com",
ownerName = "backend.faceattendence.morpho.com",
packagePath = ""
)
)
public class CityEndpoint {
private static final Logger logger = Logger.getLogger(CityEndpoint.class.getName());
private static final int DEFAULT_LIST_LIMIT = 20;
static {
// Typically you would register this inside an OfyServive wrapper. See: https://code.google.com/p/objectify-appengine/wiki/BestPractices
ObjectifyService.register(City.class);
}
/**
* Returns the {@link City} with the corresponding ID.
*
* @param id the ID of the entity to be retrieved
* @return the entity with the corresponding ID
* @throws NotFoundException if there is no {@code City} with the provided ID.
*/
@ApiMethod(
name = "get",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.GET)
public City get(@Named("id") Long id) throws NotFoundException {
logger.info("Getting City with ID: " + id);
City city = ofy().load().type(City.class).id(id).now();
if (city == null) {
throw new NotFoundException("Could not find City with ID: " + id);
}
return city;
}
/**
* Inserts a new {@code City}.
*/
@ApiMethod(
name = "insert",
path = "city",
httpMethod = ApiMethod.HttpMethod.POST)
public City insert(City city) {
// Typically in a RESTful API a POST does not have a known ID (assuming the ID is used in the resource path).
// You should validate that city.id has not been set. If the ID type is not supported by the
// Objectify ID generator, e.g. long or String, then you should generate the unique ID yourself prior to saving.
//
// If your client provides the ID then you should probably use PUT instead.
ofy().save().entity(city).now();
logger.info("Created City.");
return ofy().load().entity(city).now();
}
/**
* Updates an existing {@code City}.
*
* @param id the ID of the entity to be updated
* @param city the desired state of the entity
* @return the updated version of the entity
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code City}
*/
@ApiMethod(
name = "update",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.PUT)
public City update(@Named("id") Long id, City city) throws NotFoundException {
// TODO: You should validate your ID parameter against your resource's ID here.
checkExists(id);
ofy().save().entity(city).now();
logger.info("Updated City: " + city);
return ofy().load().entity(city).now();
}
/**
* Deletes the specified {@code City}.
*
* @param id the ID of the entity to delete
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code City}
*/
@ApiMethod(
name = "remove",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("id") Long id) throws NotFoundException {
checkExists(id);
ofy().delete().type(City.class).id(id).now();
logger.info("Deleted City with ID: " + id);
}
/**
* List all entities.
*
* @param cursor used for pagination to determine which page to return
* @param limit the maximum number of entries to return
* @return a response that encapsulates the result list and the next page token/cursor
*/
@ApiMethod(
name = "list",
path = "city",
httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<City> list(@Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {
limit = limit == null ? DEFAULT_LIST_LIMIT : limit;
Query<City> query = ofy().load().type(City.class).limit(limit);
if (cursor != null) {
query = query.startAt(Cursor.fromWebSafeString(cursor));
}
QueryResultIterator<City> queryIterator = query.iterator();
List<City> cityList = new ArrayList<City>(limit);
while (queryIterator.hasNext()) {
cityList.add(queryIterator.next());
}
return CollectionResponse.<City>builder().setItems(cityList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}
private void checkExists(Long id) throws NotFoundException {
try {
ofy().load().type(City.class).id(id).safe();
} catch (com.googlecode.objectify.NotFoundException e) {
throw new NotFoundException("Could not find City with ID: " + id);
}
}
}
我想在城市和人之间建立关系,使得许多人可以属于一个城市。
问题:
这是 class 对这种关系的正确建模吗?如果不是请告诉我一对一和一对多关系的正确模型
如何通过 java 代码(端点)和 API 资源管理器为这种关系在数据存储中插入记录?
是否需要使用@Parent注解或@Index注解?
建立这个关系后,如果我删除一个城市,那么所有属于该城市的人都必须自动删除。这种建模能够实现吗?请告诉我执行此操作的代码。如果不是那么我怎样才能实现这种使用关系?
我无法回答有关 Google 端点的任何问题,但是使用指向城市的关键字段对 Person 进行建模的基本思想可能是正确的 - 假设一个城市有很多人。您需要 @Index 关键字段,以便您可以查询城市中的人。请注意,此查询将最终保持一致,因此如果您 adding/removing 一个城市中有很多人,您需要在停止添加人员和执行删除之间设置延迟。
您可以对此建模,使 City 成为 Person 的@Parent。这会消除最终的一致性,但这意味着你永远不能将一个人移动到一个新的城市。这也意味着由于单个实体组的事务吞吐量限制,该城市中的任何城市或个人每秒都不能更改超过一次。假设您实际上是在谈论 Persons and Cities,您可能不想要这个。但这取决于你的数据集。
首先阅读下面 link 中关于 objectify 组的讨论:
how to insert record in objectify entity having one-to-one or one-to-many relationship in android
因此,基于密钥(即网络安全密钥)而不是基于 ID 设计 API 是一种更好的方法,因为 ID 在数据存储中不是唯一的。
所以我 将我的人物模型 class 更改为 :
@Entity
public class Person {
@Id
Long id;
String name;
@Parent
@Index
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
Key<City> city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsafeKey() {
return Key.create(city.getKey(), Person.class, id).getString();
}
}
getWebsafeKey() 会 return 为拥有 parent 信息的人 class 提供网络安全密钥。我想要这个网络安全密钥,这样我就可以通过查询密钥直接检索存储的实体。
对于城市模型 class,因为它没有 parent getWebsafeKey() 方法,所以看起来像:
public String getWebsafeKey() {
return Key.create( City.class, id).getString();
}
问题2的答案:
在问题中插入城市将是相同的,意味着 city endpoint 的 insert() 方法没有变化。在城市中插入人物将如下所示:
@ApiMethod(
name = "insert",
path = "city/{city_web_safe_key}/person",
httpMethod = ApiMethod.HttpMethod.POST)
public Person insert(@Named("city_web_safe_key") String cityWebSafeKey,Person person) {
Key<City> cityKey = Key.create(cityWebSafeKey);
person.city = Ref.create(cityKey);
ofy().save().entity(person).now();
logger.info("Created Person.");
return ofy().load().entity(person).now();
}
同样,您还必须更改具有 "id" 参数的所有其他 @ApiMethod,因为当您从模型 class 自动生成端点时,所有 @ApiMethod 都将基于 "id" 如问题所示。所以你必须用 "web safe key" 替换 "id" 参数。 同样的事情也适用于城市端点方法。
为了更好地了解参数,您应该[单击此处][2]
例如,person 端点的获取方法如下所示:
@ApiMethod(
name = "get",
path = "person/{person_websafe_key}",
httpMethod = ApiMethod.HttpMethod.GET)
public Site get(@Named("person_websafe_key") String personWSKey) throws NotFoundException {
logger.info("Getting person with WSkey: " + personWSKey);
Person person = (Person) ofy().load().key(Key.create(personWSKey)).now();
if (person == null) {
throw new NotFoundException("Could not find person with WSKey: " + personWSKey);
}
return person;
}
问题 4 的答案:
Objectify 不会强制开发人员进行此类删除。这完全取决于您有什么样的要求。这是 City 的 remove 方法,它也将删除该城市中存在的人。
@ApiMethod(
name = "remove",
path = "city/{city_web_safe_key}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("city_web_safe_key") String cityWSKey) throws NotFoundException {
Key<City> cityKey = Key.create(cityWSKey);
checkExists(cityKey);
//ofy().delete().key(cityKey).now();
ofy().delete().keys(ofy().load().ancestor(cityKey).keys().list());
}
问题 1 和 3 的答案
上面的答案已经涵盖了详细知识 see documentation
我有如下 class 城市的模型:
@Entity
public class City {
@Id
Long id;
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
我有另一个模型class下面给出的人:
@Entity
public class Person {
@Id
Long id;
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
Key<City> city;
}
之后,我使用 android studio 为 class 生成端点并进行部署。
这里是生成端点的代码:
PersonEndpoint
@Api(
name = "personApi",
version = "v1",
resource = "person",
namespace = @ApiNamespace(
ownerDomain = "backend.faceattendence.morpho.com",
ownerName = "backend.faceattendence.morpho.com",
packagePath = ""
)
)
public class PersonEndpoint {
private static final Logger logger = Logger.getLogger(PersonEndpoint.class.getName());
private static final int DEFAULT_LIST_LIMIT = 20;
static {
// Typically you would register this inside an OfyServive wrapper. See: https://code.google.com/p/objectify-appengine/wiki/BestPractices
ObjectifyService.register(Person.class);
}
/**
* Returns the {@link Person} with the corresponding ID.
*
* @param id the ID of the entity to be retrieved
* @return the entity with the corresponding ID
* @throws NotFoundException if there is no {@code Person} with the provided ID.
*/
@ApiMethod(
name = "get",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.GET)
public Person get(@Named("id") Long id) throws NotFoundException {
logger.info("Getting Person with ID: " + id);
Person person = ofy().load().type(Person.class).id(id).now();
if (person == null) {
throw new NotFoundException("Could not find Person with ID: " + id);
}
return person;
}
/**
* Inserts a new {@code Person}.
*/
@ApiMethod(
name = "insert",
path = "person",
httpMethod = ApiMethod.HttpMethod.POST)
public Person insert(Person person) {
// Typically in a RESTful API a POST does not have a known ID (assuming the ID is used in the resource path).
// You should validate that person.id has not been set. If the ID type is not supported by the
// Objectify ID generator, e.g. long or String, then you should generate the unique ID yourself prior to saving.
//
// If your client provides the ID then you should probably use PUT instead.
ofy().save().entity(person).now();
logger.info("Created Person.");
return ofy().load().entity(person).now();
}
/**
* Updates an existing {@code Person}.
*
* @param id the ID of the entity to be updated
* @param person the desired state of the entity
* @return the updated version of the entity
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code Person}
*/
@ApiMethod(
name = "update",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.PUT)
public Person update(@Named("id") Long id, Person person) throws NotFoundException {
// TODO: You should validate your ID parameter against your resource's ID here.
checkExists(id);
ofy().save().entity(person).now();
logger.info("Updated Person: " + person);
return ofy().load().entity(person).now();
}
/**
* Deletes the specified {@code Person}.
*
* @param id the ID of the entity to delete
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code Person}
*/
@ApiMethod(
name = "remove",
path = "person/{id}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("id") Long id) throws NotFoundException {
checkExists(id);
ofy().delete().type(Person.class).id(id).now();
logger.info("Deleted Person with ID: " + id);
}
/**
* List all entities.
*
* @param cursor used for pagination to determine which page to return
* @param limit the maximum number of entries to return
* @return a response that encapsulates the result list and the next page token/cursor
*/
@ApiMethod(
name = "list",
path = "person",
httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<Person> list(@Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {
limit = limit == null ? DEFAULT_LIST_LIMIT : limit;
Query<Person> query = ofy().load().type(Person.class).limit(limit);
if (cursor != null) {
query = query.startAt(Cursor.fromWebSafeString(cursor));
}
QueryResultIterator<Person> queryIterator = query.iterator();
List<Person> personList = new ArrayList<Person>(limit);
while (queryIterator.hasNext()) {
personList.add(queryIterator.next());
}
return CollectionResponse.<Person>builder().setItems(personList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}
private void checkExists(Long id) throws NotFoundException {
try {
ofy().load().type(Person.class).id(id).safe();
} catch (com.googlecode.objectify.NotFoundException e) {
throw new NotFoundException("Could not find Person with ID: " + id);
}
}
}
城市端点
@Api(
name = "cityApi",
version = "v1",
resource = "city",
namespace = @ApiNamespace(
ownerDomain = "backend.faceattendence.morpho.com",
ownerName = "backend.faceattendence.morpho.com",
packagePath = ""
)
)
public class CityEndpoint {
private static final Logger logger = Logger.getLogger(CityEndpoint.class.getName());
private static final int DEFAULT_LIST_LIMIT = 20;
static {
// Typically you would register this inside an OfyServive wrapper. See: https://code.google.com/p/objectify-appengine/wiki/BestPractices
ObjectifyService.register(City.class);
}
/**
* Returns the {@link City} with the corresponding ID.
*
* @param id the ID of the entity to be retrieved
* @return the entity with the corresponding ID
* @throws NotFoundException if there is no {@code City} with the provided ID.
*/
@ApiMethod(
name = "get",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.GET)
public City get(@Named("id") Long id) throws NotFoundException {
logger.info("Getting City with ID: " + id);
City city = ofy().load().type(City.class).id(id).now();
if (city == null) {
throw new NotFoundException("Could not find City with ID: " + id);
}
return city;
}
/**
* Inserts a new {@code City}.
*/
@ApiMethod(
name = "insert",
path = "city",
httpMethod = ApiMethod.HttpMethod.POST)
public City insert(City city) {
// Typically in a RESTful API a POST does not have a known ID (assuming the ID is used in the resource path).
// You should validate that city.id has not been set. If the ID type is not supported by the
// Objectify ID generator, e.g. long or String, then you should generate the unique ID yourself prior to saving.
//
// If your client provides the ID then you should probably use PUT instead.
ofy().save().entity(city).now();
logger.info("Created City.");
return ofy().load().entity(city).now();
}
/**
* Updates an existing {@code City}.
*
* @param id the ID of the entity to be updated
* @param city the desired state of the entity
* @return the updated version of the entity
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code City}
*/
@ApiMethod(
name = "update",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.PUT)
public City update(@Named("id") Long id, City city) throws NotFoundException {
// TODO: You should validate your ID parameter against your resource's ID here.
checkExists(id);
ofy().save().entity(city).now();
logger.info("Updated City: " + city);
return ofy().load().entity(city).now();
}
/**
* Deletes the specified {@code City}.
*
* @param id the ID of the entity to delete
* @throws NotFoundException if the {@code id} does not correspond to an existing
* {@code City}
*/
@ApiMethod(
name = "remove",
path = "city/{id}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("id") Long id) throws NotFoundException {
checkExists(id);
ofy().delete().type(City.class).id(id).now();
logger.info("Deleted City with ID: " + id);
}
/**
* List all entities.
*
* @param cursor used for pagination to determine which page to return
* @param limit the maximum number of entries to return
* @return a response that encapsulates the result list and the next page token/cursor
*/
@ApiMethod(
name = "list",
path = "city",
httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<City> list(@Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {
limit = limit == null ? DEFAULT_LIST_LIMIT : limit;
Query<City> query = ofy().load().type(City.class).limit(limit);
if (cursor != null) {
query = query.startAt(Cursor.fromWebSafeString(cursor));
}
QueryResultIterator<City> queryIterator = query.iterator();
List<City> cityList = new ArrayList<City>(limit);
while (queryIterator.hasNext()) {
cityList.add(queryIterator.next());
}
return CollectionResponse.<City>builder().setItems(cityList).setNextPageToken(queryIterator.getCursor().toWebSafeString()).build();
}
private void checkExists(Long id) throws NotFoundException {
try {
ofy().load().type(City.class).id(id).safe();
} catch (com.googlecode.objectify.NotFoundException e) {
throw new NotFoundException("Could not find City with ID: " + id);
}
}
}
我想在城市和人之间建立关系,使得许多人可以属于一个城市。 问题:
这是 class 对这种关系的正确建模吗?如果不是请告诉我一对一和一对多关系的正确模型
如何通过 java 代码(端点)和 API 资源管理器为这种关系在数据存储中插入记录?
是否需要使用@Parent注解或@Index注解?
建立这个关系后,如果我删除一个城市,那么所有属于该城市的人都必须自动删除。这种建模能够实现吗?请告诉我执行此操作的代码。如果不是那么我怎样才能实现这种使用关系?
我无法回答有关 Google 端点的任何问题,但是使用指向城市的关键字段对 Person 进行建模的基本思想可能是正确的 - 假设一个城市有很多人。您需要 @Index 关键字段,以便您可以查询城市中的人。请注意,此查询将最终保持一致,因此如果您 adding/removing 一个城市中有很多人,您需要在停止添加人员和执行删除之间设置延迟。
您可以对此建模,使 City 成为 Person 的@Parent。这会消除最终的一致性,但这意味着你永远不能将一个人移动到一个新的城市。这也意味着由于单个实体组的事务吞吐量限制,该城市中的任何城市或个人每秒都不能更改超过一次。假设您实际上是在谈论 Persons and Cities,您可能不想要这个。但这取决于你的数据集。
首先阅读下面 link 中关于 objectify 组的讨论: how to insert record in objectify entity having one-to-one or one-to-many relationship in android 因此,基于密钥(即网络安全密钥)而不是基于 ID 设计 API 是一种更好的方法,因为 ID 在数据存储中不是唯一的。 所以我 将我的人物模型 class 更改为 :
@Entity
public class Person {
@Id
Long id;
String name;
@Parent
@Index
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
Key<City> city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsafeKey() {
return Key.create(city.getKey(), Person.class, id).getString();
}
}
getWebsafeKey() 会 return 为拥有 parent 信息的人 class 提供网络安全密钥。我想要这个网络安全密钥,这样我就可以通过查询密钥直接检索存储的实体。
对于城市模型 class,因为它没有 parent getWebsafeKey() 方法,所以看起来像:
public String getWebsafeKey() {
return Key.create( City.class, id).getString();
}
问题2的答案: 在问题中插入城市将是相同的,意味着 city endpoint 的 insert() 方法没有变化。在城市中插入人物将如下所示:
@ApiMethod(
name = "insert",
path = "city/{city_web_safe_key}/person",
httpMethod = ApiMethod.HttpMethod.POST)
public Person insert(@Named("city_web_safe_key") String cityWebSafeKey,Person person) {
Key<City> cityKey = Key.create(cityWebSafeKey);
person.city = Ref.create(cityKey);
ofy().save().entity(person).now();
logger.info("Created Person.");
return ofy().load().entity(person).now();
}
同样,您还必须更改具有 "id" 参数的所有其他 @ApiMethod,因为当您从模型 class 自动生成端点时,所有 @ApiMethod 都将基于 "id" 如问题所示。所以你必须用 "web safe key" 替换 "id" 参数。 同样的事情也适用于城市端点方法。 为了更好地了解参数,您应该[单击此处][2]
例如,person 端点的获取方法如下所示:
@ApiMethod(
name = "get",
path = "person/{person_websafe_key}",
httpMethod = ApiMethod.HttpMethod.GET)
public Site get(@Named("person_websafe_key") String personWSKey) throws NotFoundException {
logger.info("Getting person with WSkey: " + personWSKey);
Person person = (Person) ofy().load().key(Key.create(personWSKey)).now();
if (person == null) {
throw new NotFoundException("Could not find person with WSKey: " + personWSKey);
}
return person;
}
问题 4 的答案: Objectify 不会强制开发人员进行此类删除。这完全取决于您有什么样的要求。这是 City 的 remove 方法,它也将删除该城市中存在的人。
@ApiMethod(
name = "remove",
path = "city/{city_web_safe_key}",
httpMethod = ApiMethod.HttpMethod.DELETE)
public void remove(@Named("city_web_safe_key") String cityWSKey) throws NotFoundException {
Key<City> cityKey = Key.create(cityWSKey);
checkExists(cityKey);
//ofy().delete().key(cityKey).now();
ofy().delete().keys(ofy().load().ancestor(cityKey).keys().list());
}
问题 1 和 3 的答案 上面的答案已经涵盖了详细知识 see documentation