java - 将数据库模型与网络模型分开

标签 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;
}

首先我想做一个接口(interface),但是当你从 DAO 检索数据时,DAO 返回类而不是接口(interface),所以我认为不能这样做,我找到的唯一解决方案是做一个“ProductUtils "从“PersistentProduct”转换为“Product”,反之亦然。

最佳答案

最优雅的方法是为 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()对于每个被引用的实体 toMany-db-Product 引用的实体仍然被更新的 Product 引用,尽管它们没有在更新的 Product 中列出。你必须调用resetPictures()getPictures()获取正确的列表,其中将包含存储在数据库中的原始产品或来自网络的更新产品的所有 toMany() 实体引用。

更新地址 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();
}

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

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

注意 此答案中给出的代码既不完整也未经过测试,只是作为如何解决此问题的提示。正如上面所指出的,这个解决方案仍然有一些限制,必须加以处理。

关于java - 将数据库模型与网络模型分开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23417415/

相关文章:

java - Logstash由于错误而停止处理:(NameError)无法加载(ext)(org.jruby.ext.openssl.OpenSSL)

java - 我的主类似乎没有添加对象

android - Espresso with Firebase - 异步加载

android - 具有layout_height ="wrap_content"的android XML布局中的ImageView具有顶部和底部填充

php - 正确的对象实例化/持久化排序和注释

java - Java中的文件操作

android - Android-x86 中没有音频

java.sql.SQLIntegrityConstraintViolationException : Column 'library_idlibrary' cannot be null

php - Kohana3 ORM : loading Key/Value Attributes

java - 数组 : selection sort doesn't display