简体   繁体   English

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

[英]Robospice storing object that extends ArrayList in database via Ormlite

Background 背景

I have been trying to modify the Robospice Ormlite example code , which I have been successful to run. 我一直在尝试修改Robospice Ormlite示例代码 ,我已成功运行该代码 The only changes I have made is that I have a JSON response that contains an array of objects. 我所做的唯一更改是我有一个包含对象数组的JSON响应。

I created 2 classes: 我创建了2个类:

public class Foos extends ArrayList<Foo>
public class Foo

I had initial problems, as my JSON response is a pure array with no outer container. 我遇到了初始问题,因为我的JSON响应是一个没有外部容器的纯数组。 I read via google groups that the way to solve this is to create a "fake" class (Foos) that extends an ArrayList. 我通过谷歌小组了解到解决这个问题的方法是创建一个扩展ArrayList的“假”类(Foos)。 This produced the following code: 这产生了以下代码:

public class FooRequest extends SpringAndroidSpiceRequest< Foos > {

   private String baseUrl;

    public FooRequest() {
        super( Foos.class );
        this.baseUrl = "http://somewhere.com/jsonurl";
    }

    @Override
    public Foos loadDataFromNetwork() throws RestClientException {
        Ln.d( "Call web service " + baseUrl );
        return getRestTemplate().getForObject( baseUrl, Foos.class );
    }
}

I then created the following service code, adapted from the examples. 然后我创建了以下服务代码,改编自示例。

public class MySpiceService 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( Foos.class );

        // init
        RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper( application, "sample_database.db", 2 );
        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 );

        // web services support xml responses
        MappingJacksonHttpMessageConverter jsonConverter = new MappingJacksonHttpMessageConverter();
        FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        final List< HttpMessageConverter< ? >> listHttpMessageConverters = restTemplate.getMessageConverters();

        listHttpMessageConverters.add( jsonConverter );
        listHttpMessageConverters.add( formHttpMessageConverter );
        listHttpMessageConverters.add( stringHttpMessageConverter );
        restTemplate.setMessageConverters( listHttpMessageConverters );
        return restTemplate;
    }

}

The problem 问题

The code runs without any force closes however I never hit the RequestListener inner class within my activity.Neither the success or failure message methods are fired, and it seems quite difficult to debug, so it feels like A "silent failure". 代码在没有任何强制关闭的情况下运行但是我从未在我的activity中触及RequestListener内部类。成功或失败消息方法都被触发,并且调试似乎很难,所以感觉就像是“静默失败”。

    public final class MyRequestListener implements RequestListener< Foos > {

        @Override
        public void onRequestFailure( SpiceException spiceException ) {
            Toast.makeText( SampleSpiceActivity.this, "failure", Toast.LENGTH_SHORT ).show();
        }

        @Override
        public void onRequestSuccess( final Articles result ) {
            Toast.makeText( SampleSpiceActivity.this, "success", Toast.LENGTH_SHORT ).show();

        }
    }

What I have tried 我试过了什么

I have tried to annotate the class Foo, with Ormlite annotations, to see if the library needed a helping hand, but still no luck. 我试图用Ormlite注释来注释类Foo,看看这个库是否需要帮助,但仍然没有运气。 As outlined below: 如下所述:

@DatabaseTable
public class Foo {

    @DatabaseField(generatedId = true)
    private int id;

    @DatabaseField
    private String someText;

}

I wonder if this is a result of the Foos class when I actually want a database table storing Foo. 当我真的想要一个存储Foo的数据库表时,我想知道这是否是Foos类的结果。 Any advice would be great! 任何建议都会很棒!

This question is not really a bug in RoboSpice, but a limitation of the ORM Lite model. 这个问题实际上并不是RoboSpice中的错误,而是ORM Lite模型的限制。

If you want to serialize a collection of Foo using ORMLite, then you must use serialize a class that is a collection of Foo. 如果要使用ORMLite序列化Foo集合,则必须使用序列化作为Foo集合的类。 You approach is right. 你接近是对的。 Nevertheless, you can't just get rid of it to store the Foo elements individually. 然而,你不能只是摆脱它来单独存储Foo元素。 You not only have to use the Foos class to parse the response but also to store data in the database. 您不仅需要使用Foos类来解析响应,还需要将数据存储在数据库中。

Foos should : Foos应该:

  • define an id 定义一个id
  • be annotated using DataBaseTable and DataField and Foreign collection 使用DataBaseTable和DataField以及Foreign集合进行注释

The problem is that you can't annotate a class and saying "I am a Foreig Collection". 问题是你不能注释一个类并说“我是一个Foreig集合”。 This annotation can only be used on fields, not on classes. 此注释只能用于字段,而不能用于类。 So If your class would "hold" a collection, that would work, but not for a class that "is a" collection. 因此,如果你的班级将“持有”一个集合,那将是有效的,但不适用于“是一个”集合的类。

So, I believe that the short answer is : no, you can't do that with ORM Lite. 所以,我认为简短的回答是:不,你不能用ORM Lite做到这一点。 You must store a top class like Foos, but it should be serializable for ORM Lite and for this it needs to have a collection field, and can't be a collection directly. 你必须存储像Foos这样的顶级类,但它应该是ORM Lite的可序列化的,为此它需要有一个集合字段,而不能直接收集。

To add on to this excellent question, I was also experiencing this 'silent failure' and did not know what to do. 为了补充这个优秀的问题,我也遇到了这种“沉默的失败”,并且不知道该怎么做。 I eventually selected inside Android Studios to see all the messages in logcat, so not only the android errors, but everything. 我最终在Android工作室内选择了查看logcat中的所有消息,因此不仅是android错误,而是一切。 I did this by selecting "Verbose" and "No Filters". 我通过选择“详细”和“无过滤器”来做到这一点。

logcat的

When I ran my app, I discovered that the reason why I was getting a silent error was because I did not generate unique ID for my SQL and this caused it to bomb out. 当我运行我的应用程序时,我发现我收到无提示错误的原因是因为我没有为我的SQL生成唯一的ID,这导致它被炸毁。

 Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: post.ID (code 1555)

I fixed it by doing this on my outer class ID field which allowed it to generate unique IDs by itself: 我通过在外部类ID字段上执行此操作来修复它,这允许它自己生成唯一ID:

@DatabaseField(allowGeneratedIdInsert=true, generatedId=true)
private int ID;

As @Snicolas said, you should change to Collection instead of ArrayList. 正如@Snicolas所说,你应该改为Collection而不是ArrayList。 I wanted to do more or less the same but without the result object, my workaround on this question RoboSpice persist JSON array with OrmLite should work for you. 我想做或多或少相同但没有结果对象,我在这个问题上的解决方法RoboSpice坚持使用OrmLite的JSON数组应该适合你。

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

    // getters and setters
    ...
}

@DatabaseTable
public class Foo {
    @DatabaseField(id = true)
    private int id;
    @DatabaseField(foreign = true)
    private Foos foos;

    // getters and setters
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM