2013-04-05 28 views
5

Tôi đang sử dụng RoboSpice với Spring cho Android và muốn tồn tại một mảng JSON đối tượng với OrmLite. GSON được sử dụng cho JSON marshalling. Với bộ nhớ đệm mặc định, mọi thứ hoạt động như mong đợi. Nhưng OrmLite dường như không thích mảng các đối tượng.RoboSpice duy trì mảng JSON với OrmLite

Đây là một phiên bản đơn giản của JSON:

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

Tôi muốn tồn tại này trong đối tượng sau đây:

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

    // getters and setters 
    ... 
} 

Dựa trên ví dụ RoboSpice OrmLite tôi đã tạo ra những điều sau đây GsonSpringAndroidSpiceService lớp để thêm OrmLite CacheManager. Đây là nơi mà vấn đề bắt đầu.

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

Điều này dẫn đến các lỗi sau:

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

Khi tôi thay đổi classCollection.add(Foo.class);-classCollection.add(Foo[].class); tôi nhận được lỗi sau:

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

Bất cứ một ý tưởng làm thế nào để xử lý một mảng JSON với OrmLite CacheManager?

+0

Có thể là một bản sao của http://stackoverflow.com/q/15801315/693752 – Snicolas

+0

@Snicolas tôi không muốn giới thiệu một lớp kết quả bổ sung, xem câu trả lời của tôi về cách giải quyết. – Uipko

Trả lời

6

Tôi đã tìm được một công việc xung quanh vấn đề này. Tôi đã thêm một đối tượng kết quả phụ có chứa mảng các đối tượng. Tất nhiên điều này chỉ có thể xảy ra nếu bạn có thể thao tác JSON. Vẫn không thực sự hài lòng với điều này bởi vì tôi đã giới thiệu một lớp vô dụng cho mô hình của tôi.

Vì vậy, tôi JSON trông giống như:

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

Và tôi đã thêm các lớp sau đây để giữ kết quả JSON:

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

    // getters and setters 
    ... 
} 

Cũng thêm mối quan hệ đối ngoại của lớp Foo:

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

    // getters and setters 
    ... 
} 
+0

Đẹp nhất, nó sẽ là giá trị chấp nhận trả lời của bạn. Tuy nhiên, đối với những người không thể sửa đổi các json, không có thay thế: bạn phải giới thiệu một lớp học mới để bọc danh sách. – Snicolas

+0

Đối với các hồ sơ: Tôi đã đấu tranh với vấn đề này và tôi đã có 'riêng ForeignCollection kết quả' và nó đã không hoạt động. Thay đổi 'ForeignCollection' thành' Collection' đã khắc phục được sự cố. – Nasir

+0

@Snicolas, giải pháp nào nếu tôi không cần thay đổi đối tượng json? –

3

Tôi đã tìm được cách phù hợp với mình. Tôi đã không thay đổi json của tôi.

@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); 
      } 
     } 

    } 


} 
+0

Rất tuyệt! Bạn có thể cung cấp cho chúng tôi đầu ra của JSON của bạn không? – Guicara

+0

Bạn có thể tìm thấy ở đây. https://api.github.com/repos/octo-online/robospice/contributors –

+1

Ví dụ làm việc đầy đủ có thể được tìm thấy ở đây https://github.com/blandware/android-atleap –

0

tôi vật lộn với điều này cả ngày hôm nay và cuối cùng đã tìm cách lưu một mảng JSON thành một cơ sở dữ liệu SQLite sử dụng Robospice Xuân Android mà không sửa đổi JSON.

Đây là bài JSON mảng của tôi trở về từ máy chủ của tôi:

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

này cũng tương tự như JSON trong câu hỏi này:

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

Bước 1:

Bạn sẽ cần phải tạo 2 lớp ở phía bên android.

Một đối tượng bình thường mà bạn muốn lưu khỏi mảng. Trong trường hợp của tôi, tôi có một đối tượng được gọi là "Post" và máy chủ của tôi trả về một mảng "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; 

Đối tượng khác sẽ là đối tượng bao bọc bao quanh mảng, tôi gọi là "EmbedPost" của tôi.

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

Bằng việc xác định một int gọi là ID trong lớp EmbedPost của tôi, tôi có hiệu quả tạo ra một đối tượng rằng nếu tôi chuyển đổi sang JSON sẽ trông như thế này:

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

Đây là một cách hiệu quả một chuỗi JSON trông rất giống với những gì Uipko sử dụng trong giải pháp của mình.

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

Bước 2:

Bây giờ bạn kiên trì nó bằng cách sử 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; 
    } 

} 

Hãy chắc chắn thêm cả lớp EmbedPost.class và Post.class vào lớp của bạnCollection vì ORMLite không thể thực hiện công việc của mình mà không cần bạn kiên trì cả hai. Bạn đã sử dụng ForeignKeys khi bạn viết lên các đối tượng của bạn và những khóa ngoại này phải gắn với một thứ gì đó vì thế cả hai lớp đều phải tồn tại.

Nếu bạn gặp sự cố, hãy thử sử dụng logcat để tìm ra. Bạn có thể phải đọc tất cả các tin nhắn và không chỉ là những thông báo lỗi. Xem bài của tôi vào đây để xem làm thế nào để đọc tất cả các thông điệp logcat:

Robospice storing object that extends ArrayList in database via Ormlite

Các vấn đề liên quan