Google App Engine与JPA数据竞赛

时间:2014-12-09 01:40:43

标签: google-app-engine jpa

我基本上有一个票务系统,其中票证有一个号码,该号码存储有关于注册它的用户的数据。票号设置很大,但不是唯一的,所以如果两个完全相同的票号被发送到数据存储区足够接近它们,我需要防止数据覆盖。这是否可以使用GAE JPA?一个例子:

@Entity(name = "Ticket")
public class Ticket {
    @Id
    private String id;
    private String kisokId;
}


public class TicketActivationServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException , ServletException{
        Ticket ticket = new Ticket();
        ticket.setTicketId(req.getParameter("ticketId"));
        ticket.setKioskId(req.getParameter("kisokId"));

        EntityManager em = null;
        try{
            em = EMF.get().createEntityManager();
            //can I first check for the existence of this ticket
            Ticket persistedTicket = em.find(Ticket.class, ticketId);
            if(persistedTicket != null)
                //now what? Can't make any assumption this won't change before the next call.

            //then can I lock out other persist calls to the same ticket before persisting this object?
            em.persist(ticket);
        }
        finally{
            if(em != null)
                em.close();
        }
    }
}

现在,如果几乎同时有两个调用来到servlet

http://localhost:8888//ticketactivation?ticketId=12345&kioskId=1

http://localhost:8888//ticketactivation?ticketId=12345&kioskId=2

我需要对第一个成功做出回应并对最后一个回应做出回应。这个方案有可能吗?

1 个答案:

答案 0 :(得分:1)

在故障单中添加版本号,并在事务中执行更新。

交易{

中的

  • 读取数据存储区中现有故障单的版本号
  • 更新要保存的票证(版本+ 1)
  • 覆盖数据存储区中的故障单

}

如果您在事务中更新了您读取的故障单,那么事务将自动回滚,因为它有冲突。

侧面说明:切换到客观化而不是JPA,你的生活会更好。