Skip to content

Instantly share code, notes, and snippets.

@ts-3156
Created March 5, 2011 14:33
Show Gist options
  • Save ts-3156/856391 to your computer and use it in GitHub Desktop.
Save ts-3156/856391 to your computer and use it in GitHub Desktop.
sample code to store too big data in datastore.
/**
* 一人分のTwitterUserData2を保存。既に保存されていた場合は重複して保存してしまう<br>
* 既存のデータをこのメソッド呼出より前に削除する必要あり<br>
* 削除せずに更新したほうが効率がよい
* @param data フォロー、フォロワー、データ作成日等を含むオブジェクト
* @param updateCount 更新回数。レガシーな理由によりこういう形になった
* @return 保存が成功したかどうか
*/
public static boolean storeTwitterUserData2(TwitterUserData2 data, int updateCount){
if(data == null || data.getFollowingUsers() == null || data.getFollowersUsers() == null || data.getCreatedDate() == null){
log.warning(data.getName() + ", fail to store because of invalid data.");
return false;
}
boolean isStored = true;
long start = 0, end = 0;
start = System.currentTimeMillis();
ArrayList<TwitterUserData2> dataToStore = new ArrayList<TwitterUserData2>();
Date createdDate = data.getCreatedDate();
Date updatedDate = null;
if(data.getUpdatedDate() != null)
updatedDate = data.getUpdatedDate();
ArrayList<ArrayList<String>> followingList = TwitterUtil.separateUsers(data.getFollowingUsers(), 1500);
ArrayList<ArrayList<String>> followersList = TwitterUtil.separateUsers(data.getFollowersUsers(), 1500);
// ループの中にあると効率悪いから外にだしました 2011/03/08
int loopLimit = Math.min(followingList.size(), followersList.size());
for(int i = 0; i < loopLimit; i++){
TwitterUserData2 d = new TwitterUserData2(data.getName(), followingList.get(i), followersList.get(i), createdDate);
if(i == 0){
d.setRemovingUsers(data.getRemovingUsers());
d.setRemovedUsers(data.getRemovedUsers());
d.setNameToIdMap(data.getNameToIdMap());
}
if(updatedDate != null)
d.setUpdatedDate(updatedDate);
dataToStore.add(d);
}
if(followingList.size() >= followersList.size()){
for(int i = followersList.size(); i < followingList.size(); i++){
TwitterUserData2 d = new TwitterUserData2(data.getName(), followingList.get(i), null, createdDate);
if(updatedDate != null)
d.setUpdatedDate(updatedDate);
dataToStore.add(d);
}
}
else{
for(int i = followingList.size(); i < followersList.size(); i++){
TwitterUserData2 d = new TwitterUserData2(data.getName(), null, followersList.get(i), createdDate);
if(updatedDate != null)
d.setUpdatedDate(updatedDate);
dataToStore.add(d);
}
}
isStored = store2(dataToStore, updateCount);
end = System.currentTimeMillis();
if(isStored)
log.info(data.getName() + ", successfully stored., time: " + (double)(end - start)/1000 + "seconds");
else
log.warning(data.getName() + ", fail to store., time: " + (double)(end - start)/1000 + "seconds");
return isStored;
}
/**
* このトランザクションはデータの不整合を起こす可能性がある<br>
* その問題は他のメソッドで解消している。slim3を使ってグローバルなトランザクションを利用すれば
* この問題は解決するかも
* @param dataList ひとり分のデータを複数に分割したList
* @param updateCount
* @return
*/
private static boolean store2(ArrayList<TwitterUserData2> dataList, int updateCount){
boolean isStored = true;
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
ArrayList<TwitterUserData2Cupsul> dataToStore = new ArrayList<TwitterUserData2Cupsul>(dataList.size());
for(int i = 0; i < dataList.size(); i++){
TwitterUserData2Cupsul c = new TwitterUserData2Cupsul(dataList.get(i), dataList.size(), i);
if(dataList.get(i).getUpdatedDate() != null){
c.setUpdatedDate(dataList.get(i).getUpdatedDate());
}
c.setVersion(2);
c.setUpdateCount(updateCount);
dataToStore.add(c);
}
try {
for(TwitterUserData2Cupsul data: dataToStore){
tx.begin();
pm.makePersistent(data);
tx.commit();
}
} finally {
if (tx.isActive()){
tx.rollback();
isStored = false;
}
pm.close();
}
return isStored;
}
@kimukou
Copy link

kimukou commented Mar 6, 2011

Math.min(followingList.size(), followersList.size()) 等ループ無いに計算式を入れるより、
事前に計算後に固定値としてループは回した方がよいです。
トランザクション処理もrollback等でエラーが出ることもあると思うのでtry-catchで囲んだ方がいいですが
そこまでするとコードがごてごてするかな?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment