我使用 Java 使用 Google App Engine,并通过 JPA 使用 Datastore。我想为每个用户保存个人资料图片:
@Entity
public class User implements Serializable {
@Id
private String userId;
private String imageKey; // saves BlobKey.getKeyString()
// ... other fields and getter/setter methods ...
}
如果用户想要更改他们的个人资料图像,我(应该)更新 imageKey 字段并删除与旧 imageKey 关联的旧图像。
删除 Blobstore 值与数据存储事务分开进行。如果在数据存储事务期间调用该方法,无论事务提交成功还是重试,都会立即生效。
这似乎我不能将更新 imageKey 和删除旧图像作为一个原子操作,它也会影响到 Java。
这是我做这项工作的尝试:
public class Engine implements ServletContextListener {
private EntityManagerFactory emf;
private BlobstoreService blobstoreService;
// Servlet will call getUser, modify returned object, and call updateUser with that object
public User getUser(final String userId) throws EngineException {
return doTransaction(new EngineFunc<User>() { // Utility method for create Entity manager and start transaction
@Override
public User run(EntityManager em) throws EngineException {
return em.find(User.class, key);
}
});
}
public void updateUser(final User user) throws EngineException {
doTransaction(new EngineFunc<Void>() {
@Override
public Void run(EntityManager em) throws EngineException {
em.merge(user);
return null;
}
});
user.purgeOldImages(blobstoreService);
}
// ... Other methods ...
}
public class User {
@Transient
private transient Set<String> oldImageList = new CopyOnWriteArraySet<>();
public void setImageKey(String imageKey) {
if (this.imageKey != null) {
oldImageList.add(this.imageKey);
}
this.imageKey = imageKey;
if (imageKey != null) {
oldImageList.remove(imageKey);
}
}
public void purgeOldImages(BlobstoreService blobService) {
Set<BlobKey> toDelete = new HashSet<>();
for (String s : oldImageList) {
toDelete.add(new BlobKey(s));
oldImageList.remove(s);
}
blobService.delete(toDelete.toArray(new BlobKey[0]));
}
// ... Other methods ...
}
我认为这既不是“美丽”也不是正确的代码。有正确的方法吗?