你不能用你所設置的實體做到這一點,因爲你詢問的任務,並插入新任務的時間之間,你不能保證別人不會已經插入一個新的任務與你插入的任務衝突。即使您使用交易,任何併發添加的衝突任務也不會成爲交易實體組的一部分,因此存在違反約束條件的可能性。
您可以修改您的體系結構,而不是每個任務都具有爲其創建的員工的引用,每個員工都包含爲該員工創建的任務集合?通過這種方式,當您查詢員工的衝突任務時,員工將在您的事務的實體組中被加時間戳,並且如果其他人在完成新任務之前將新任務加入其中,則會拋出併發修改異常,您會然後重試。但是,是的,將您的查詢和您的投入放在同一個交易中。
這裏閱讀有關的事務,實體組和樂觀併發:https://code.google.com/p/objectify-appengine/wiki/Concepts#Transactions
至於確保您的任務不重疊,你只需要檢查是否兩端日起新任務的開始是日起同一員工的任何以前任務的範圍。您還需要檢查您是否設置了一個新的任務,該任務在前一個任務的日期範圍之前開始並結束。我建議爲每個測試使用composite.and過濾器,然後將這三個複合過濾器合併到composite.or過濾器中,這將是您最終應用的過濾器。可能會有更簡單的方法,但這是我的方法:
請注意,這些過濾器不適用於我建議的新體系結構。也許我會刪除它們。 ////////限於分配給同一員工的任務 Filter sameEmployeeTask = new FilterPredicate(「createdFor」,FilterOperator.EQUAL,thisCreatedFor);
/////////Check if new startDate is in range of the prior task
Filter newTaskStartBeforePriorTaskEnd =
new FilterPredicate("endDate", FilterOperator.GREATER_THAN, thisStartDate);
Filter newTaskStartAfterPriorTaskStart =
new FilterPredicate("startDate", FilterOperator.LESS_THAN, thisStartDate);
Filter newTaskStartInPriorTaskRange =
CompositeFilterOperator.and(sameEmployeeTask, newTaskStartBeforePriorTaskEnd, newTaskStartAfterPriorTaskStart);
/////////Check if new endDate is in range of the prior task
Filter newTaskEndBeforePriorTaskEnd =
new FilterPredicate("endDate", FilterOperator.GREATER_THAN, thisEndDate);
Filter newTaskEndAfterPriorTaskStart =
new FilterPredicate("startDate", FilterOperator.LESS_THAN, thisEndDate);
Filter newTaskEndInPriorTaskRange =
CompositeFilterOperator.and(sameEmployeeTask, newTaskEndBeforePriorTaskEnd, newTaskEndAfterPriorTaskStart);
/////////Check if this Task overlaps the prior one on both sides
Filter newTaskStartBeforePriorTaskStart =
new FilterPredicate("startDate", FilterOperator.GREATER_THAN_OR_EQUAL, thisStartDate);
Filter newTaskEndAfterPriorTaskEnd =
new FilterPredicate("endDate", FilterOperator.LESS_THAN_OR_EQUAL, thisEndDate);
Filter PriorTaskRangeWithinNewTaskStartEnd = CompositeFilterOperator.and(sameEmployeeTask ,newTaskStartBeforePriorTaskStart, newTaskEndAfterPriorTaskEnd);
/////////Combine them to test if any of the three returns one or more tasks
Filter newTaskOverlapPriorTask = CompositeFilterOperator.or(newTaskStartInPriorTaskRange,newTaskEndInPriorTaskRange,PriorTaskRangeWithinNewTaskStartEnd);
/////////Proceed
Query q = new Query("Task").setFilter(newTaskOverlapPriorTask);
PreparedQuery pq = datastore.prepare(q);
如果您不返回任何結果,那麼您沒有任何重疊,因此請繼續並保存新任務。
確定,但不應該是一個事務中做什麼? – justatester
對,你不能像你設置你的實體一樣。查看我答案頂部的新編輯。 – Jibbyj
@justatester Jibbyj是對的......不幸的是,您目前的設置方式,您無法真正做到。我會考慮改變你的種類的設計,以確保未來可以規避這種情況。 – Patrice