I have an issue when I want to add a Review
to a Product
. If I call the setReview
method for two different product, the review gets created with the same id. So both products have the same review whereas I need two different reviews. In my case, newReview is true, the ArrayList reviews is empty, a new Review
is created and added to the reviews. The review is stored when productDao.update(product)
is called. I want to know why the created review id gets an already used id. The product is partially activated.
@Override
public Boolean setReview(Product product, ProductResult result, Boolean admin) {
OAuthUserId currentUserId = getCurrentOAuthUserId();
boolean demoUser = currentUserId.equals(ServerConstants.DEMO_ID);
if (!demoUser) {
ProductDao productDao = productDaoProvider.get();
ReviewDao reviewDao = reviewDaoProvider.get();
List<Review> reviews = product.getReviews();
productDao.activateAll(reviews);
if (reviews == null) {
reviews = new ArrayList<Review>();
product.setReviews(reviews);
}
Review currentReview = null;
for (Review review : reviews) {
if (review.getoAuthUserId().equals(currentUserId)
&& admin.equals(review.isAdmin())) {
currentReview = review;
break;
}
}
boolean newReview = currentReview == null;
if (newReview) {
currentReview = new Review();
currentReview.setoAuthUserId(currentUserId);
currentReview.setAdmin(admin);
reviews.add(currentReview);
}
if (result == null) {
reviews.remove(currentReview);
// denormalization
productDao.activate(product.getProductParent());
productDao.update(product);
reviewDao.delete(currentReview);
} else {
currentReview.setResult(result);
currentReview.setTimestamp(new Date());
if (newReview) {
// denormalization
productDao.activate(product.getProductParent());
productDao.update(product);
} else {
reviewDao.update(currentReview);
}
}
}
return !demoUser;
}
The Review
entity:
public class Review extends DatastoreObject implements Serializable {
@Index
@Embed
private OAuthUserId oAuthUserId;
private ProductResult result;
private boolean admin;
private ProductResult verifiedResult;
private Date timestamp;
public Review() {
}
}
@Entity(kind = "com.server.model.domain.DatastoreObject", allocateIdsBy = 100)
public class DatastoreObject implements Serializable {
@Id
protected Long id = null;
protected Integer version = 0;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DatastoreObject other = (DatastoreObject) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
I have a different version of twig (beta6). In instanceToEntity
, there is a call to maybeSetAllocatedId
. At the end of this method datastore.encodeKeyDetails.getId()
returns an available id. Then the call encoder.encode(instance, Path.EMPTY_PATH, false);
changes the datastore.encodeKeyDetails.getId()
value to an existing id. Then the call createEntity
stores the entity with an incorrect id.
In FieldTranslator
PropertyTranslator translator = encoder(field, instance);
encoded = translator.encode(value, childPath, indexed(field));
The translator
has a datastore object and encodeKeyDetails.getId()
returns the available id. encoded
result is an empty collections. So it's like the available id is not used.
What do you mean by fixed? in a future version?
I don't really understand what is going on because when encode(Object instance, Path path, boolean indexed)
is called for the id of the new Review
in FieldTranslator
, instance
is null, path
is id and indexed
is false. It's weird because I have this problem only for that kind of entity. For other entities when I add an instance to a list, and update the father of that list, I have no issue.
What I will do is to migrate to the latest code, and see if it fixes the issue.
Is it normal in dev mode, if two entities of different kinds have the same id? How do you make sure that an id is available for a kind?
I don't really understand what is going on because when
encode(Object instance, Path path, boolean indexed)
is called for the id of the newReview
inFieldTranslator
,instance
is null,path
is id andindexed
is false.
It's weird because I have this problem only for that kind of entity. For other entities when I add an instance to a list, and update the father of that list, I have no issue.
What I will do is to migrate to the latest code, and see if it fixes the issue.
Is it normal in dev mode, if two entities of different kinds have the same id?
How do you make sure that an id is available for a kind?
I don't really understand what is going on because when
encode(Object instance, Path path, boolean indexed)
is called for the id of the newReview
inFieldTranslator
,instance
is null,path
is id andindexed
is false.
The Review
entity has an @Embed
field oAuthUserId
. All my entities extend from DatastoreObject
which defines a @Id
field.
public class Review extends DatastoreObject implements Serializable {
@Index
@Embed
private OAuthUserId oAuthUserId;
private ProductResult result;
private boolean admin;
private ProductResult verifiedResult;
private Date timestamp;
}
@Entity(kind = "com.server.model.domain.DatastoreObject", allocateIdsBy = 100)
public class DatastoreObject implements Serializable {
@Id
protected Long id = null;
protected Integer version = 0;
}
public class OAuthUserId extends DatastoreObject implements Serializable {
@Index
private String userId;
@Index
private OAuthProvider provider;
}
I removed the @Id
from the embedded entity, and it's working. I don't have to change my model since OAuthUserId
is only used as embedded which makes sense. I was wondering what will be the impact of that change (removing the @Id
from OAuthUserId
) for the existing data.
I checked the current data in the datastore, and there is no entity OAuthUserId
, so I guess removing the @Id
will have no impact on existing data since that property was never stored. What do you think?
I checked the current data in the datastore, and there is no entity
OAuthUserId
, so I guess removing the@Id
will have no impact on existing data since that property was never stored. What do you think?