Коллекции в ORMLite

Здравствуйте, я хочу сохранить некоторые данные коллекций с помощью ORMlite в своем приложении для Android. Например :

class Person {
  @DatabaseField(generatedId=true)
  private int id;

  @DatabaseField
  private String name;

  @DatabaseField
  private String surname;

  @ForeignCollectionField
  private Collections<Phone> phones;
}

class Phone {
  @DatabaseField(generatedId=true)
  private int id;

  @DatabaseField
  private String number;

  @DatabaseField
  private String type; 
}

Как я должен это сделать, чтобы сохранить эту коллекцию.

ИЗМЕНИТЬ

Я использую ForeignCollectionField, как вы мне сказали. Но теперь у меня другой вопрос - возможна ли такая конструкция (я немного изменил класс)

@DatabaseTable
public class Student {

    @DatabaseField(generatedId=true)
    private int id;

    @DatabaseField
    private String name;

    @DatabaseField
    private String surname;

    @DatabaseField
    private String semestr;

    @ForeignCollectionField
    private Collection<Adres> adres;
}

public class Adres implements Serializable {

    @DatabaseField(generatedId=true)
    private int id;

    @DatabaseField(foreign=true, columnName="student_id")
    private Student student;

    @DatabaseField
    private String miasto;

    @DatabaseField
    private String ulica;

    @DatabaseField
    private String nr;

    @ForeignCollectionField
    private Collection<Phone> phone;
}

public class Phone {

    @DatabaseField(generatedId=true)
    private int id;

    @DatabaseField
    private String number;

    @DatabaseField(foreign=true, columnName="adres_id" )
    private Adres adres;
}

Я строю эту структуру, у меня есть 3 табелы.

Student queryForStudentMarcin = simpleDao.queryForId(studentMarcin.getId());
Collection<Adres> adres = queryForStudentMarcin.getAdres();

for (Adres a : adres) {
    int id = a.getId();
    String miasto = a.getMiasto();
    String ulica = a.getUlica();
    String nr = a.getNr();
}

Затем я делаю это, и появляется ошибка:

04-03 15:55:58.392: ERROR/AndroidRuntime(6506): FATAL EXCEPTION: main
04-03 15:55:58.392: ERROR/AndroidRuntime(6506): java.lang.NullPointerException
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.j256.ormlite.field.FieldType.buildForeignCollection(FieldType.java:579)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:58)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:107)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.j256.ormlite.stmt.SelectIterator.next(SelectIterator.java:120)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.example.orm.MainActivity.dodajDoBazyCollection(MainActivity.java:140)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.example.orm.MainActivity$2.onClick(MainActivity.java:66)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.view.View.performClick(View.java:2408)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.view.View$PerformClick.run(View.java:8816)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.os.Handler.handleCallback(Handler.java:587)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.os.Looper.loop(Looper.java:123)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at android.app.ActivityThread.main(ActivityThread.java:4627)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at java.lang.reflect.Method.invokeNative(Native Method)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at java.lang.reflect.Method.invoke(Method.java:521)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
04-03 15:55:58.392: ERROR/AndroidRuntime(6506):     at dalvik.system.NativeStart.main(Native Method)

Какие-либо предложения ?

Изменить2

Проблема заключалась в чтении данных из БД. Эта процедура работает нормально, теперь это хорошо, но я просто использую ее, чтобы понять ORMlite. Большое спасибо Грею за помощь.

protected void czytajZBazy() throws SQLException {

    Dao<Student, Integer> simpleDao = getHelper().getSimpleDao();
    Dao<Adres, Integer> adresDao = getHelper().getAdresDao();
    Dao<Phone, Integer> phoneDao = getHelper().getPhoneDao();

    /**
     * wyswietl adresy dla studenta Marcin
     */
    QueryBuilder<Student, Integer> qbStudent = simpleDao.queryBuilder();;
    Where<Student, Integer> where = qbStudent.where();
    where.eq("name", "Marcin");
    PreparedQuery<Student> prepare = qbStudent.prepare();
    CloseableIterator<Student> iterator = simpleDao.iterator(prepare);
    while(iterator.hasNext()){
        Log.v("inside ", "loop");
        Student next = iterator.next();
        Log.v("sudent", ""+next.getId()+" "+next.getName()+" "+next.getSurname());

        QueryBuilder<Adres, Integer> adresQB = adresDao.queryBuilder();
        Where<Adres, Integer> where2 = adresQB.where();

        where2.eq("student_id", next.getId());

        PreparedQuery<Adres> preparedAdres = adresQB.prepare();
        CloseableIterator<Adres> iterator2 = adresDao.iterator(preparedAdres);

        while(iterator2.hasNext()){
            Log.v("iterator po adresie", "!!");
            Adres nextAdres = iterator2.next();
            Log.v("Adres", ""+nextAdres.getId()+" "+nextAdres.getMiasto());
            //wypisz telefony 
            QueryBuilder<Phone, Integer> queryPhone = phoneDao.queryBuilder();
            Where<Phone, Integer> where3 = queryPhone.where();
            where3.eq("adres_id", nextAdres.getId());

            PreparedQuery<Phone> preparedPhone = queryPhone.prepare();
            CloseableIterator<Phone> iterator3 = phoneDao.iterator(preparedPhone);

            while(iterator3.hasNext()){
                Log.v("inside phone iterator", "");
                Phone next2 = iterator3.next();
                Log.v("phone", ""+next2.getId()+" "+next2.getNumber());
            }
            iterator3.close();
        }
        iterator2.close();
    }
    iterator.close();
}

person Bandzio    schedule 02.04.2011    source источник
comment
Вы можете связаться со мной напрямую Bandzio? Нажмите на мое имя в нижней части главной страницы ORMLite, а затем перейдите на страницу Contact Grey: ormlite.com   -  person Gray    schedule 04.04.2011
comment
@Gray Как я могу получить ForeignCollection в свой курсор. Ссылка: stackoverflow.com/questions/22071367/   -  person nitesh    schedule 28.02.2014


Ответы (1)


Существует ряд ресурсов и руководств, помогающих использовать ORMLite под Android.

http://ormlite.com/docs/android
http://ormlite.com/docs/android-examples

Чтобы сохранить коллекцию, вы должны сначала получить Dao для класса, а затем создать каждый из объектов с помощью Dao:

Dao<Person, Integer> personDao =
    DaoManager.createDao(androidConnectionSource, Person.class);
for (Person person : personCollection) {
    personDao.create(person);
}

Почти то же самое и для вашего класса Phone.


Он действительно спрашивал о том, как использовать функцию ForeignCollectionField ORMLite. Документацию для этого можно найти здесь:

http://ormlite.com/docs/foreign-collection

Существует также пример проекта, который его использует. В приведенном выше примере вам не хватает поля Person внутри Phone. Если у человека есть коллекция объектов телефона, то каждый объект телефона должен иметь соответствующего человека. В ORMLite это называется «посторонний объект».

http://ormlite.com/docs/foreign-object

person Gray    schedule 02.04.2011
comment
Мои сомнения относятся скорее к тому, как аннотировать поле коллекции в классе. Например, у меня есть объект Person: Name : Martin; Surname : XXX; Phones : id = 1; number = 123123123; type = mobile ; id = 2 ;number = 877777123; type = mobile; id = 3; number = 127378643; type = mobile. Мне нужен Table Person и Table Phone (создайте в onCreate() ) для хранения моих данных. В JPA я использую здесь что-то вроде @OneToMany, чтобы аннотировать полевые телефоны лично. Как добиться этого в ORMLite? Также как добиться @ManyToMany. Как аннотировать поля коллекции в классе? Спасибо за помощь и за OMRLite Grey :) - person Bandzio; 02.04.2011
comment
Пожалуйста, отредактируйте свой вопрос @Bandzio, чтобы лучше представить ваши вопросы, и я отредактирую свой ответ. - person Gray; 02.04.2011
comment
Я понял, что мне просто нужно Keep It Simple. Если в моем классе есть несколько полей коллекции, секрет заключается в том, чтобы создать их вручную. Вся коллекция со своей таблицей. Я просто хочу найти какую-нибудь волшебную аннотацию, которая сделает все за меня. Но если у кого-то есть какие-то советы с этим подходом, я буду благодарен. - person Bandzio; 02.04.2011
comment
ORMLite не такая волшебная, как другие библиотеки ORM. Я прокомментировал свой ответ, чтобы показать, как использовать посторонние объекты. Вот чего не хватало. - person Gray; 03.04.2011
comment
ForeignCollectionField не может быть разрешен здесь... Наиболее вероятная причина моей зависимости от maven: исключения› ‹исключение› ‹groupId›com.j256.ormlite‹/groupId› ‹artifactId›ormlite-core‹/artifactId› ‹/exclusion› ‹/exclusions› ‹/dependency› Любой? - person Richard Lalancette; 10.07.2012
comment
4.41 последняя версия. ForeignCollectionField был добавлен в 4.16. ormlite.com/changelog.txt - person Gray; 11.07.2012
comment
Мы столкнулись с некоторыми проблемами во время итерации внешней коллекции. Похоже, что некоторые соединения с базой данных не закрываются. Поэтому мы повторяем, используя next() и closeLastIterator для внешней коллекции. РЕДАКТИРОВАТЬ: кажется, что это также объяснение (stackoverflow.com/a/7074205/1152444) - person Dino Velić; 04.12.2017