本文介绍了Google App Engine与JPA数据竞赛的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上有一个票务系统,其中一张票有一个号码,存储有关于注册用户的数据。票号设置很大,但不是唯一的,所以如果两个相同的故障单号在时间上足够接近地发送到数据存储以便它们可能发生冲突,那么我需要防止数据覆盖。这可能使用GAE JPA吗?一个例子:

  @Entity(name =Ticket)
public class Ticket {
@Id
私人字符串ID;
私人字符串kisokId;


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

EntityManager em = null;
尝试{
em = EMF.get()。createEntityManager();
//我可以首先检查是否存在此票证
Ticket persistedTicket = em.find(Ticket.class,ticketId);
if(persistedTicket!= null)
//现在是什么?无法做出任何假设,这在下次通话之前不会改变。

//然后,我可以在保留此对象之前将其他持续调用锁定到相同的故障单吗?
em.persist(ticket);
}
finally {
if(em!= null)
em.close();



code
$ b现在如果有两个电话来几乎在同一时间的servlet

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

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

我需要为第一个成功做出回应,然后拒绝最后一个。这是可能的吗?

解决方案

为您的票证添加版本号并在交易中进行更新。


$ b

在事务{b / b


  • 中读取数据存储区中现有故障单的版本号


  • 更新要保存的故障单(版本+ 1)

  • 覆盖故障单中的故障单



  • 如果您读取的故障单在事务处理期间已更新,那么事务将自动回滚,因为它具有冲突。



    注意:切换到objectify而不是JPA,您的生活会更好。


    I essentially have a ticketing system where a ticket has a number which is stored with data about a user who registered it. The ticket number set is large, but not unique so I need to prevent data overwrites if two identical ticket numbers are sent to the datastore close enough in time that they could collide. Is this possible using GAE JPA? An example:

    @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();
            }
        }
    }
    

    Now if two calls come to the servlet at nearly the same time

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

    I need to respond with success for the first and respond with a rejection of the last one. Is this possible in this scheme?

    解决方案

    Add a version number to your ticket and do your updates in a transaction.

    in the transaction {

    • Read the version number of the existing ticket in the datastore
    • update the ticket you want to save with (version + 1)
    • overwrite ticket in datastore

    }

    If the ticket you read was updated during your transaction, then the transaction will rollback automatically because it has a collision.

    on side note : switch to objectify instead of JPA, your life will be better.

    这篇关于Google App Engine与JPA数据竞赛的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 17:21