问题描述:

@Entity

public class Category {

@Id

private Long id;

private String name;

private String description;

@Load

private List<Ref<Subcategory>> subcategories = new ArrayList<Ref<Subcategory>>();

@Load

private Ref<Image> image;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public List<Subcategory> getSubcategories() {

List<Subcategory> scs = new ArrayList<Subcategory>();

for (Ref<Subcategory> sc : this.subcategories) {

scs.add(sc.get());

}

return scs;

}

public void setSubcategory(Subcategory subcategory) {

this.subcategories.add(Ref.create(subcategory));

}

public Image getImage() {

if(image != null) {

return image.get();

}

return null;

}

public void setImage(Image image) {

this.image = Ref.create(image);

}

}

@Entity

public class Subcategory {

@Id

private Long id;

private String name;

private String description;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

public class CategoryDTO {

private Long id;

@NotNull

private String name;

private String description;

private List<Subcategory> subcategories = new ArrayList<Subcategory>();

private Long imageId;

public CategoryDTO() {

}

public CategoryDTO(Category category) {

this.id = category.getId();

this.name = category.getName();

this.description = category.getDescription();

this.subcategories = category.getSubcategories();

if (category.getImage() != null) {

this.imageId = category.getImage().getId();

}

}

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public List<Subcategory> getSubcategories() {

return subcategories;

}

public void setSubcategories(List<Subcategory> subcategories) {

this.subcategories = subcategories;

}

public Long getImageId() {

return imageId;

}

public void setImageId(Long imageId) {

this.imageId = imageId;

}

}

CategoryDAO

public class CategoryDAO {

private static final Logger log = Logger.getLogger(CategoryService.class.getName());

public static QueryResultIterator<Category> getCategories() {

QueryResultIterator<Category> categories = ofy().load().type(Category.class).iterator();

return categories;

}

}

public class SubcategoryDAO {

public static Subcategory createSubcategory(Long categoryId, Subcategory data) {

// save sub category

Subcategory subcategory = new Subcategory();

if (data.getName() != null) {

subcategory.setName(data.getName());

}

if (data.getDescription() != null) {

subcategory.setDescription(data.getDescription());

}

ofy().save().entity(subcategory).now();

Category category =

ofy().load().type(Category.class).id(categoryId).get();

category.setSubcategory(subcategory);

ofy().save().entity(category).now();

return subcategory;

}

}

CategoryService

@Path("/categories")

public class CategoryService {

@GET

@Produces(MediaType.APPLICATION_JSON)

public String getCategories() {

try {

List<CategoryDTO> categories = new ArrayList<CategoryDTO>();

QueryResultIterator<Category> cats = CategoryDAO.getCategories();

while (cats.hasNext()) {

categories.add(new CategoryDTO(cats.next()));

}

Map<String, List<CategoryDTO>> map = new HashMap<String, List<CategoryDTO>>();

map.put("categories", categories);

return Helper.prepareResponse(map);

} catch (Exception e) {

LogService.getLogger().severe(e.getMessage());

throw new WebApplicationException(500);

}

}

}

Problem:-

When i hit getCategories service, it is showing unexpected behaviour.Instead of showing all the subcategories, it is showing random no of different subcategories every time.

For example say,

first i save a category "c"

then i save subcategories "sa", "sb" and "sc"

On hitting getCategry service,

Expected Behaviour -

{

"status": 200,

"categories" : [{

"name":a,

"subcategories": [

{

"name":"sa"

},

{

"name":"sb"

},

{

"name":"sc"

}

]

}]

}

Outputs i get is something like this -

{

"status": 200,

"categories" : [{

"name":a,

"subcategories": [

{

"name":"sa"

},

{

"name":"sc"

}

]

}]

}

or

{

"status": 200,

"categories" : [{

"name":a,

"subcategories": [{

"name":"sb"

}]

}]

}

网友答案:

To summarize this question, you're performing a query (give list of all categories) and getting back inconsistent results.

This is the system working as advertised. Read this: https://cloud.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency

Eventual consistency is something that you learn to live with and work around when you need it. There is no way to force a query to be strongly consistent without changing the structure of your data - say, put it under a single entity group - but that has repercussions as well. There is no free lunch if you want a globally replicated, infinitely-scalable database.

In addition to eventual consistency, the datastore has no defined ordering behavior if you do not specify a sort order in your query. So that might add to your confusion.

网友答案:

Welcome to the wonderful world of eventual consistency. When I encountered something like this, using ObjectifyService.begin() instead of ObjectifyService.ofy() resolved it. Unlike ofy(), begin() gets you fresh data every time.

相关阅读:
Top