从网络模型中分离数据库模型

时间:2014-05-01 22:02:33

标签: java android orm model greendao

我正在使用GreenDAO和Volley。所以我有以下问题:当我发出网络请求时,我需要用GSON解析,所以我有一个模型来表示从服务器和其他模型中检索的实体来表示GreenDAO对象。有没有办法让每个模型只有1个类表示为GSON和ORM类?

类产品:

@SerializedName("id")
private String id;

@SerializedName("pictures")
private List<Picture> pictures;

get & set

类PersistentProduct:

private Long id;
private List<Picture> pictures;

/** To-many relationship, resolved on first access (and after reset). Changes to to-many relations are not persisted, make changes to the target entity. */
public List<PersistencePicture> getPictures() {
    if (pictures == null) {
        if (daoSession == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        PersistencePictureDao targetDao = daoSession.getPersistencePictureDao();
        List<PersistencePicture> picturesNew = targetDao._queryPersistenceProduct_Pictures(id);
        synchronized (this) {
            if(pictures == null) {
                pictures = picturesNew;
            }
        }
    }
    return pictures;
}

首先我想创建一个接口,但是当你从DAO中检索数据时,DAO返回的是类而不是接口,所以我认为不能这样做,我找到的唯一解决方案就是做一个&# 34; ProductUtils&#34;转换自&#34; PersistentProduct&#34;到&#34;产品&#34;反之亦然。

1 个答案:

答案 0 :(得分:1)

最优雅的方法是为greendao实现一个小扩展,以便您可以在模式创建期间指定序列化名称。

例如:

<强> de.greenrobot.daogenerator.Property.java

// in PropertyBuilder append these lines
public PropertyBuilder setSerializedName(String sname) {
    // Check the sname on correctness (i.e. not empty, not containing illegal characters)
    property.serializedName = sname;
    return this;
}

// in Property append these lines
private String serializedName = null;

public boolean isSerialized() {
    return serializedName != null;
}

entity.ftl 中,在第24行(package ${entity.javaPackage};之后)添加此行:

<#if property.serializedName??>
import com.google.gson.annotations.SerializedName;
</#if>

在第55行(在<#list entity.properties as property>之后)

之后
<#if property.serializedName??>
@SerializedName("${property.serializedName}")
</#if>

之后你应该可以使用以下限制:使用生成的greendao-entity进行截击:

  1. 如果您通过网络获得产品,则数据库中没有任何更改。您必须致电insertOrReplace()
  2. 如果您从数据库获取产品并通过网络发送,则某些不需要的字段可能会被序列化(即myDaodaoSession
  3. 如果您通过网络获得产品并致电insertOrReplace()“网络” - 产品将被保留,现有产品将被其替换引用的实体将不会如果没有为每个人调用insertOrReplace(),请更新或保留!
  4. 如果您通过网络获得产品并为每个被引用的实体调用insertOrReplace(),那么更新的产品仍然会引用db-Product引用的多个实体,尽管它们未在更新的产品中列出。您必须致电resetPictures()getPictures()以获取正确的列表,该列表将包含所有toMany() - 由存储在数据库中的原始产品或来自网络的更新产品引用的实体。
  5. 更新地址2。

    要阻止序列化daoSessionmyDao,您可以使用以下ExclusionStrategy

    private static class TransientExclusionStrategy implements ExclusionStrategy {
        public boolean shouldSkipClass(Class<?> clazz) {
            return (clazz.getModifiers() & java.lang.reflect.Modifier.TRANSIENT) != 0;
        }
    
        public boolean shouldSkipField(FieldAttributes f) {
            return f.hasModifier(java.lang.reflect.Modifier.TRANSIENT);
        }
    }
    

    更新地址1.,3。和4。

    作为快速解决方案,您可以在实体的KEEP-SECTIONS中添加以下方法:

    public void merge(DaoSession s) {
        s.insertOrReplace(this);
    
        // do this for all toMany-relations accordingly
        for (Picture p : getPictures()) {
            s.insertOrReplace(p);
            newPics.add(p.getId());
        }
        resetPictures();
    }
    

    这将导致原始实体更新并附加到会话和dao。此外,网络产品引用的每个图片都将被保留或更新。原始实体引用的图片,但不是网络实体引用的图片保持不变,并合并到列表中。

    这远非完美,但它显示了去哪里和做什么。接下来的步骤是在一个事务中执行merge()中完成的所有操作,然后将不同的merge - 方法集成到 dao.ftl 中。

    注意 这个答案中给出的代码既不完整也不经过测试,而是暗示如何解决这个问题。如上所述,这个解决方案仍有一些限制,必须加以处理。