在play 2.x应用程序中,我有一个邮政请求,用于从父表中删除子员。如果有多个带有相同请求参数的请求,我该如何要求播放以锁定儿童列表以避免并发访问并重复删除相同的记录?如果重复的请求非常紧密地发送,则像以下一样抛出一个例外:
javax.persistence.optimisticlockexception:数据已更改。更新 [0] rows sql [从channel_detail delete delete where id =?和 成员_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;
}
我不确定播放本身是否具有防止这种情况发生的机制,而被抛出的例外已经是锁定策略的一种形式。我认为主要问题是数据有时间在获取何时和要删除条目时进行更改,因此它会执行以下操作之一:
-
以不同的方式实施删除方法,以使成员的查找和删除一次发生(免责声明:我对Ebean都不熟悉,所以我完全不确定它如何处理交易管理)
-
捕获
OptimisticLockException
,然后在几秒钟后再次尝试删除,然后重复例如。3次,如果再次失败的方式