5

我将 RoboSpice 与 Spring for Android 一起使用,并希望使用 OrmLite 持久化 JSON 对象数组。GSON 用于 JSON 编组。使用默认缓存,一切都按预期工作。但是 OrmLite 似乎不喜欢对象数组。

这是 JSON 的简化版本:

[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}]

我想将其保留在以下对象中:

@DatabaseTable
public class Foo {
    @DatabaseField(id = true)
    private int id;
    @DatabaseField
    private String title;

    // getters and setters
    ...
}

基于 RoboSpice OrmLite 示例,我创建了以下 GsonSpringAndroidSpiceService 类来添加 OrmLite CacheManager。这就是问题开始的地方。

public class CustomGsonSpringAndroidSpiceService extends GsonSpringAndroidSpiceService
{
    @Override
    public CacheManager createCacheManager(Application application)
    {
        // add persisted classes to class collection
        List<Class<?>> classCollection = new ArrayList<Class<?>>();
        classCollection.add(Foo.class);

        // init
        CacheManager cacheManager = new CacheManager();
        cacheManager.addPersister(new InDatabaseObjectPersisterFactory(
            application, new RoboSpiceDatabaseHelper(
                application, "database.db", 1), classCollection));
        return cacheManager;
    }
}

这会导致以下错误:

RequestProcessor.java:174(22356): java.lang.RuntimeException: Class [Lcom.example.model.Foo; is not handled by any registered factoryList

当我更改为时classCollection.add(Foo.class);classCollection.add(Foo[].class); 我收到以下错误:

RequestProcessor.java:174(22601): 14:42:23.112 pool-5-thread-1 An unexpected error occured when processsing request CachedSpiceRequest [requestCacheKey=foo, cacheDuration=-1, spiceRequest=com.example.app.FooRequest@4055df40]
RequestProcessor.java:174(22601): java.lang.IllegalArgumentException: No fields have a DatabaseField annotation in class [Lcom.example.app.model.Foo;

有人知道如何使用 OrmLite CacheManager 处理 JSON 数组吗?

4

3 回答 3

6

我找到了解决这个问题的方法。我添加了一个包含对象数组的额外结果对象。当然,这只有在您能够操作 JSON 时才有可能。仍然对此并不满意,因为我在我的模型中引入了一个无用的类。

所以我的 JSON 看起来像:

{ 
    "id": 1,
    "result":[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}]
}

我添加了以下类来保存 JSON 结果:

@DatabaseTable
public class FooResult {
    @DatabaseField(id = true)
    private int id;
    @ForeignCollectionField(eager = false)
    private Collection<Foo> result;

    // getters and setters
    ...
}

还添加了 Foo 类的外部关系:

@DatabaseTable
public class Foo {
    @DatabaseField(id = true)
    private int id;
    @DatabaseField
    private String title;
    @DatabaseField(foreign = true)
    private FooResult result;

    // getters and setters
    ...
}
于 2013-04-08T10:53:41.087 回答
3

我找到了适合我的方式。我没有改变我的json。

@DatabaseTable(tableName = SampleContract.Contributor.TABLE)
public class Contributor {

    @DatabaseField(generatedId = true, columnName = SampleContract.Contributor._ID)
    private int id;

    @DatabaseField(columnName = SampleContract.Contributor.LOGIN)
    public String login;

    @DatabaseField(columnName = SampleContract.Contributor.CONTRIBUTIONS)
    public int contributions;

    @DatabaseField(foreign = true)
    private ContributorsResult result;

    @SuppressWarnings("serial")
    @DatabaseTable(tableName = "contributor_list")
    public static class ContributorsResult extends ArrayList<Contributor> {

        @DatabaseField(id = true)
        private int id = 0;


        @ForeignCollectionField(eager = false)
        private Collection<Contributor> result = this;

        public Collection<Contributor> getResult() {
            return result;
        }

        public void setResult(Collection<Contributor> result) {
            if (result != null) {
                this.clear();
                this.addAll(result);
            }
        }

    }


}
于 2014-01-01T20:17:44.667 回答
0

我今天整天都在为此苦苦挣扎,最后想出了如何在不修改 JSON 的情况下使用 Robospice Spring Android 将 JSON 数组保存到 SQLite 数据库中。

这是我从服务器返回的 post JSON 数组:

[
{
"id": "5573547af58cd75df03306cc",
"name": "Simon",
"postheader": "First Post"
},
{
"id": "55735475f58cd75df03306cb",
"name": "Tyron",
"postheader": "Second Post"
}
]

这类似于此问题中的 JSON:

[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}]

第1步:

您将需要在 android 端创建 2 个类。

一个是您要从数组中保存的普通对象。就我而言,我有一个名为“Post”的对象,我的服务器返回一个“Post”数组。

@DatabaseTable(tableName = "post")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Post implements Serializable {
    @DatabaseField(id = true)
    private String id;
    @DatabaseField
    private String name;
    @DatabaseField
    private String postheader;
    @DatabaseField(foreign = true,foreignAutoCreate = true,foreignAutoRefresh = true)
    private EmbedPost posts;

另一个对象将是一个包裹数组的包装对象,我称之为“EmbedPost”。

@DatabaseTable
public class EmbedPost implements Serializable {
    @DatabaseField(allowGeneratedIdInsert=true, generatedId=true)
    private int ID;
    @ForeignCollectionField(eager = false)
    private Collection<Post> posts;

通过在我的 EmbedPost 类中定义一个名为 ID 的 int,我有效地创建了一个对象,如果我转换为 JSON,它将如下所示:

{"id": 1, "posts": [
{
"id": "5573547af58cd75df03306cc",
"name": "Simon",
"postheader": "First Post"
},
{
"id": "55735475f58cd75df03306cb",
"name": "Tyron",
"postheader": "Second Post"
}
]}

这实际上是一个 JSON 字符串,看起来与 Uipko 在他的解决方案中使用的非常相似。

{ 
    "id": 1,
    "result":[{"id": 1, "title": "Test 1"},{"id": 2, "title": "Test 3"},{"id": 3, "title": "Test 3"}]
}

第2步:

您现在使用 SpringAndroidSpiceService 持久化它。

public class AndroidSpiceService extends SpringAndroidSpiceService {
    private static final int WEBSERVICES_TIMEOUT = 10000;

    @Override
    public CacheManager createCacheManager( Application application ) {
        CacheManager cacheManager = new CacheManager();
        List< Class< ? >> classCollection = new ArrayList< Class< ? >>();

        // add persisted classes to class collection
        classCollection.add(EmbedPost.class);
        classCollection.add( Post.class );
        // init
        RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper( application, "sample_database.db", 3);
        InDatabaseObjectPersisterFactory inDatabaseObjectPersisterFactory = new InDatabaseObjectPersisterFactory( application, databaseHelper, classCollection );
        cacheManager.addPersister( inDatabaseObjectPersisterFactory );
        return cacheManager;
    }

    @Override
    public RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        // set timeout for requests

        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setReadTimeout( WEBSERVICES_TIMEOUT );
        httpRequestFactory.setConnectTimeout( WEBSERVICES_TIMEOUT );
        restTemplate.setRequestFactory( httpRequestFactory );

        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        final List<HttpMessageConverter< ? >> listHttpMessageConverters = restTemplate.getMessageConverters();

        listHttpMessageConverters.add( mappingJackson2HttpMessageConverter  );
        restTemplate.setMessageConverters( listHttpMessageConverters );
        return restTemplate;
    }

}

请务必将 EmbedPost.class 和 Post.class 添加到您的 classCollection 中,因为如果您不坚持两者,ORMLite 就无法完成其工作。您在编写对象时使用了 ForeignKeys,这些外键必须与某些东西相关联,因此两个类都必须保持不变。

如果遇到麻烦,请尝试使用 logcat 来解决。您可能必须阅读所有消息,而不仅仅是错误消息。请参阅我的帖子,了解如何阅读所有 logcat 消息:

Robospice 存储对象,通过 Ormlite 在数据库中扩展 ArrayList

于 2015-06-13T18:31:51.237 回答