使数据存储区和blobstore具有事务性

时间:2013-11-10 03:08:04

标签: java google-app-engine jpa transactions google-cloud-datastore

我使用Java使用Google App Engine,并通过JPA使用数据存储。 我想为每个用户保存个人资料图片:

@Entity
public class User implements Serializable {
    @Id
    private String userId;
    private String imageKey; // saves BlobKey.getKeyString()
    // ... other fields and getter/setter methods ...
}

如果用户想要更改其个人资料图片,我(应该)更新imageKey字段并删除与旧imageKey关联的旧图像。

但是,the document of Blobstore for Python说:

  

删除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 ...
}

我认为这既不是“美丽”也不是正确的代码。 有没有正确的方法来做到这一点?

0 个答案:

没有答案