Baq*_*qir 5 google-app-engine android objectify google-cloud-endpoints google-cloud-datastore
我有如下类 City 的模型:
@Entity
public class City {
@Id
Long id;
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Run Code Online (Sandbox Code Playgroud)
我有另一个模型类 Person 下面给出:
@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;
}
Run Code Online (Sandbox Code Playgroud)
之后,我使用 android studio 为这两个类生成端点并部署它。
这是生成的端点的代码:
个人端点
@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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
城市端点
@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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想在 City 和 Person 之间建立关系,以便许多人可以属于一个城市。 问题:
对于这种关系,这是类的正确建模吗?如果不是,请告诉我一对一和一对多关系的正确模型
如何通过java代码(端点)和API资源管理器在数据存储中插入这种关系的记录?
是否需要使用@Parent 批注或@Index 批注?
建立这种关系后,如果我删除一个城市,那么所有属于该城市的人都必须自动删除。这种建模能够实现吗?请告诉我执行此操作的代码。如果不是,那么我如何才能实现这种使用关系?
首先阅读下面链接中与 objectify groups 发生的讨论: how to insert record in objectify entity had one-to-one or one-to-many relation in android 因此,这是基于键设计 API 的更好方法(即网络安全密钥)不是基于 ID,因为 ID 在数据存储中不是唯一的。所以我将 Person 模型类更改为:
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
getWebsafeKey() 将返回具有其父信息的 person 类的网络安全密钥。我想要这个网络安全密钥,以便我可以通过查询密钥直接检索存储的实体。
对于 City 模型类,由于它没有父 getWebsafeKey() 方法,因此如下所示:
public String getWebsafeKey() {
return Key.create( City.class, id).getString();
}
Run Code Online (Sandbox Code Playgroud)
问题2的答案: 插入城市将与问题中的相同,意味着城市端点的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();
}
Run Code Online (Sandbox Code Playgroud)
同样,您还必须更改具有“id”参数的所有其他 @ApiMethod ,因为当您从模型类自动生成端点时,所有 @ApiMethod 将基于“id”,如问题所示。所以你必须用“网络安全密钥”替换“id”参数。同样的事情也适用于城市端点方法。为了更好地了解参数,您应该[单击此处][2]
例如,人员端点的 get 方法将如下所示:
@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;
}
Run Code Online (Sandbox Code Playgroud)
问题 4 的答案: Objectify 不会强制开发人员进行此类删除。这完全取决于您有什么样的要求。这是城市的删除方法,它也会删除该城市中的人员。
@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());
}
Run Code Online (Sandbox Code Playgroud)
问题1和3的答案 已经在上面的答案中涵盖,详细知识请参阅文档
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |