我搜索了"级联删除"境界的运作。遗憾的是,该功能尚未实施。我自己实现了它并在这里分享了它。
如何为Realm制作通用代码"级联删除"操作?
答案 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对象。示例如下。
public class NodeModel extends RealmObject implements IRITSerializable, IRealmCascade {
@PrimaryKey
@SerializedName("id") private String objId;
@SerializedName("parentId") private String parentId;
@SerializedName("contentType") private String nodeType;
@Required
@SerializedName("name") private String name;
@SerializedName("settings") private RealmList<ValueTypeModel> columns;
public String getObjId() {
return objId;
}
public void setObjId(String objId) {
this.objId = objId;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getNodeType() {
return nodeType;
}
public void setNodeType(String nodeType) {
this.nodeType = nodeType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmList<ValueTypeModel> getColumns() {
return columns;
}
public void setColumns(RealmList<ValueTypeModel> columns) {
this.columns = columns;
}
}
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);
}
享受您干净的数据库! :)
答案 1 :(得分:0)
我对此实现有一些变化,其他人可能会觉得有用。
在原始实现中:要遍历的RealmObject子类&#34;实现IRealmCascade&#34;。任何未实现该接口的RealmObject都将被视为叶节点(该对象将被删除,但其子节点不会被删除)。
在我的实现中:任何RealmObject / RealmList都是可遍历的(它们不需要实现任何接口)。如果该类具有不被遍历的成员,则该成员的getter使用&#34; @ SkipDelete&#34;进行注释。
/**
* 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;
}
}