播放2.0控制器并发访问并删除相同的记录

时间:2012-10-30 06:24:57

标签: concurrency playframework playframework-2.0

在play 2.x应用程序中,我有一个post请求,用于从父表中删除子成员。如果有多个请求具有相同的请求参数,我怎么能要求Play锁定子列表以避免同时访问和重复删除相同的记录?如果非常密切地发送重复请求,则抛出异常,如下所示:

  

javax.persistence.OptimisticLockException:数据已更改。更新   [0]行sql [从channel_detail删除,其中id =?和   member_id =?和channel_info_id =?] bind [null]

@BodyParser.Of(BodyParser.FormUrlEncoded.class)
public static Result removeMemberFromChannel() {
    RequestBody body = request().body();
    Map<String, String[]> dict = body.asFormUrlEncoded();
    final String memberId = dict.get("memberId") != null ? dict.get(Config.MEMBER_ID_PARAM)[0] : null;

    ChannelInfo channelInfo = ChannelInfo.getChannelForName(channelName); //method was removed to save space
    if (channelInfo != null) {
       channelInfo.removeMemberId(memberId);
       channelInfo.save();
    }
}

@Entity
@Table(name="channel")
public class ChannelInfo extends Model {
    @Id
    private Long id;

    @Constraints.Required
    private String channelName;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="channelInfo")
    private Set<ChannelDetailMember> members;

    private int membersCount = 0;

    public void removeMemberId(String memberId) {
        Iterator<ChannelDetailMember> iter = this.getMembers().iterator();
        while (iter.hasNext()) {
            ChannelDetailMember dMember = iter.next();
            if (dMember.getMemberId().equals(memberId)) {
               dMember.delete();
               membersCount--;
               break;
            }
         }
    }
}

@Entity
@Table(name="channel_detail")
public class ChannelDetailMember extends Model {

    @Id
    private Long id;

    @Constraints.Required
    private String memberId;

    @Constraints.Required
    @ManyToOne(cascade=CascadeType.PERSIST)
    ChannelInfo channelInfo;
}

1 个答案:

答案 0 :(得分:1)

我不确定Play本身是否带有防止此类事件发生的机制,抛出的异常已经是锁定策略的一种形式。我认为主要问题是数据有时间在您获取数据和删除条目之间进行更改,因此它会执行以下操作之一:

  • 以不同方式实现删除方法,以便一次性查找和删除成员(免责声明:我不熟悉EBean所以我完全不确定它是如何处理的交易管理)

  • 抓住OptimisticLockException,然后在几秒钟后再次尝试删除并重复例如如果它以同样的方式再次失败,则为3次