2016-05-02 28 views
4

レルムの "カスケード削除"操作に関する検索を行いました。残念ながらその機能はまだ実装されていません。私は自分でそれを実装してここで共有しました。レルムの "カスケード削除"

レルム「カスケード削除」操作の汎用コードの作成方法は?

+1

スタックオーバーフローは、プログラミングの質問です。あなたの質問は何ですか? – CommonsWare

+0

私はそれを終了させて​​ください...私はそれを公開しています。 –

答えて

2

1)プロジェクト

import android.util.Log; 


import java.lang.reflect.Method; 
import io.realm.RealmList; 
import io.realm.RealmObject; 
import com.company.project.models.IRealmCascade; 

/** 
*/ 

public class RealmUtils 
{ 
public static void deleteCascade(RealmObject dataObject) 
{ 
    if (dataObject == null) 
    { 
     return; 
    } 
    if(IRealmCascade.class.isAssignableFrom(dataObject.getClass())) 
    { 
     for(Method method : dataObject.getClass().getSuperclass().getDeclaredMethods()) 
     { 
      try { 
       //Ignore generated methods 
       if((method.getName().contains("realmGet$")) || (method.getName().contains("access$super"))) 
       { 
        continue; 
       } 
       Class<?> resultType = method.getReturnType(); 
       //Ignore non object members 
       if (resultType.isPrimitive()) { 
        continue; 
       } 

       if (RealmObject.class.isAssignableFrom(resultType)) { 
        //Delete Realm object 
        try { 
         RealmObject childObject = (RealmObject) method.invoke(dataObject); 
         RealmUtils.deleteCascade(childObject); 
        } catch (Exception ex) { 
         Log.e("REALM", "CASCADE DELETE OBJECT: " + ex.toString()); 
        } 
       } else if (RealmList.class.isAssignableFrom(resultType)) { 
        //Delete RealmList items 
        try { 
         RealmList childList = (RealmList) method.invoke(dataObject); 
         while(childList.iterator().hasNext()) 
         { 
          RealmObject listItem = (RealmObject)childList.iterator().next(); 
          RealmUtils.deleteCascade(listItem); 
         } 
        } catch (Exception ex) { 
         Log.e("REALM", "CASCADE DELETE LIST: " + ex.toString()); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Log.e("REALM", "CASCADE DELETE ITERATION: " + ex.toString()); 
      } 
     } 
    } 
    dataObject.deleteFromRealm(); 
} 

} 

2)プロジェクトにインターフェイスを追加するには、このコードをコピーしてください。 Realmオブジェクトがこのインタフェースを実装している場合、deleteCascadeの呼び出し後にすべての子オブジェクトが削除されます。インタフェースが実装されていない場合、この関数はRealmオブジェクトを削除しますが、子オブジェクトは削除しません。

public interface IRealmCascade { 
} 

3)Realmオブジェクトを宣言します。以下の例。

4)RealmUtils.deleteCascade(realmObject)を呼び出す必要があります。代わりにrealmObject.removeFromRealm();ローカルデータベースに 更新データ

for(NodeModel nodeItem: incomingData.getNodesList()) 
{ 
    RealmResults<NodeModel> results = bgRealm.where(NodeModel.class).equalTo("objId", nodeItem.getObjId()).findAll(); 
    if (results.size() > 0) 
    { 
     RealmUtils.deleteCascade(results.first()); 
    } 
    bgRealm.copyToRealm(nodeItem); 
} 

以下 の例は、あなたのきれいなDBをお楽しみください! :)

+1

このコードは動作しますが非常に遅いので、IDが – iGoDa

+0

のテーブルでテーブルをテーブルまたはテーブルで削除する方が速いアプローチが必要な場合は、データを大量には遅くなりますがそれはほとんどのニーズに十分に速いです。大量のデータ(数千レコードなど)を削除する必要がある場合は、バックグラウンドスレッドで実行してください。 –

+0

本当に、私は他人にそれについて警告したかっただけです。 – iGoDa

0

私はこの実装にバリエーションがあり、他の人が役に立つと思うかもしれません。

元の実装では、トラバース可能なRealmObjectサブクラス「implement IRealmCascade」。インタフェースを実装していないRealmObjectsは、リーフノードとして扱われます(オブジェクトは削除されますが、その子は削除されません)。

私の実装では:どのRealmObject/RealmListもトラバース可能です(インターフェイスを実装する必要はありません)。クラスに、走査されないメンバーがある場合、そのメンバーのゲッターには "@SkipDelete"という注釈が付けられます。

/** 
* Traverse the tree of RealmObjects, deleting the RealmObject/RealmList children 
* and the root RealmObject. 
* <br><br> 
* This method uses reflection to get the rootObject's "getter" methods. The 
* getter methods are called to get the RealmObject/RealmList children, and 
* those objects are deleted from the Realm. 
* <br><br> 
* If any of the getter methods return a RealmObject/RealmList that should NOT be 
* deleted, those getter methods should be annotated with {@link SkipDelete}. 
* 
* @param rootObject The root of the RealmObject tree 
*/ 
public static void delete(RealmObject rootObject) { 
    if (rootObject == null) { 
     return; 
    } 

    for (Method method : rootObject.getClass().getSuperclass().getDeclaredMethods()) { 
     try { 
      // Ignore non-getter methods 
      boolean noParams = method.getParameterTypes().length == 0; 
      if (!(method.getName().startsWith("get")) || !noParams) { 
       continue; 
      } 

      // Ignore primitive members 
      Class<?> resultType = method.getReturnType(); 
      if (resultType.isPrimitive()) { 
       continue; 
      } 

      // Ignore methods annotated with SkipDelete 
      if (method.isAnnotationPresent(SkipDelete.class)) { 
       continue; 
      } 

      if (RealmObject.class.isAssignableFrom(resultType)) { 
       // getter method returns a RealmObject, delete it 
       try { 
        RealmObject childObject = (RealmObject) method.invoke(rootObject); 
        delete(childObject, true); 
       } catch (Exception ex) { 
        Log.e("delete: RealmObject " + resultType.getSimpleName(), ex); 
       } 

      } else if (RealmList.class.isAssignableFrom(resultType)) { 
       // getter method returns a RealmList, delete the objects in the list 
       try { 
        RealmList childList = (RealmList) method.invoke(rootObject); 
        while (childList.iterator().hasNext()) { 
         RealmObject listItem = (RealmObject)childList.iterator().next(); 
         delete(listItem, true); 
        } 
       } catch (Exception ex) { 
        Log.e("delete: RealmList " + resultType.getSimpleName(), ex); 
       } 
      } 
     } 
     catch (Exception ex) { 
      Log.e("delete: ", ex); 
     } 
    } 

    rootObject.deleteFromRealm(); 
} 

/** 
* This annotation is used to mark a "getter" method that should be skipped 
* over on the cascading delete traversal of the RealmObject/RealmList tree. 
*/ 
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface SkipDelete { 
} 
あなたRealmObjectで

public class Design extends RealmObject { 
    private MyRealmObject1 obj1;  // do CascadeDelete on this member 
    private MyRealmObject2 obj2;  // don't do CascadeDelete on this member 

    .... 

    public MyRealmObject1 getObj1() { 
     return obj1; 
    } 

    @CascadeDelete.SkipDelete   // don't do CascadeDelete of obj2 
    public MyRealmObject2 getObj2() { 
     return obj2; 
    } 
}