Создать таблицу с полем иностранной коллекции
У меня есть этот абстрактный класс:
DomainItem
abstract public class DomainItem {
@DatabaseField(generatedId = true)
protected long id;
@ForeignCollectionField(eager = false)
protected ForeignCollection<ContentItem> contentItens;
//getters and setters
}
ContentItem:
abstract public class ContentItem {
@DatabaseField(generatedId = true)
protected long id;
@DatabaseField(foreign = true)
protected DomainItem domainItem;
@DatabaseField()
protected String content;
//getters and setters
}
И эти (не абстрактные):
@DatabaseTable()
public class PhytoterapicItem extends DomainItem{
public PhytoterapicItem(){
}
}
PhytoterapicContent
@DatabaseTable(tableName = "phytoterapiccontent")
public class PhytoterapicContent extends ContentItem {
@DatabaseField(canBeNull = false)
private String defaultName;
@DatabaseField(canBeNull = false)
private String scientificName;
//getters and setters
}
В моем DatabaseHelper я пытаюсь создать таблицы:
//DatabaseHelper
...
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(TAG, "onCreate");
TableUtils.createTable(connectionSource, PhytoterapicContent.class);
Log.i(TAG, "Created table PhytoterapicContent");
TableUtils.createTable(connectionSource, PhytoterapicItem.class);
Log.i(TAG, "Created table PhytoterapicItem");
catch{
...
}
Создается таблица PhytoterapicContent. Но я получил следующую ошибку:
java.sql.SQLException: Внешний класс коллекции br.com.project.model.ContentItem для имени столбца 'contentItens' для поля не содержит поля иностранного класса класса br.com.project.model.PhytoterapicItem
Ответы
Ответ 1
Итак, сообщение об исключении было разработано для помощи здесь. Чтобы процитировать его с удаленными именами классов:
Класс внешней коллекции ContentItem
для поля contentItens
имя столбца не содержит чужого поля класса PhytoterapicItem
Это выглядит так. Всякий раз, когда у вас есть ForeignCollection
, класс, содержащийся в коллекции, должен иметь внешнее поле для родительского класса.
В вашем случае PhytoterapicItem
расширяет класс DomainItem
, который имеет ForeignCollection
объектов ContentItem
. Это означает, что ContentItem
должно иметь внешнее поле типа PhytoterapicItem
. В противном случае, как ORMLite знать, какие из элементов ContentItem
в таблице связаны с конкретным PhytoterapicItem
.
Пример объектов Account
и Order
в документации иностранной коллекции может помочь вам с вашей схемой. Каждый Account
имеет чужой набор объектов Order
. Всякий раз, когда вы запрашиваете Account
, выполняется отдельный запрос, чтобы найти коллекцию объектов Order
, которые соответствуют конкретному Account
. Это означает, что каждый Order
должен иметь внешний объект Account
.
Ответ 2
Мне потребовалось некоторое время, чтобы заметить/понять этот критический блок из документов (http://ormlite.com/docs/foreign-collection):
Помните, что когда у вас есть поле ForeignCollection, класс в коллекции должен (в данном примере Order) иметь внешнее поле для класса с коллекцией (в этом примере Account). Если у Учетной записи есть иностранная коллекция Заказов, тогда у Ордера должно быть поле с иностранной учетной записью. Это необходимо, чтобы ORMLite мог найти заказы, соответствующие конкретной учетной записи.
Причина, по которой я был смущен, заключается в том, что я не нашел кода примера (в документах или проектах примеров), где "содержащийся класс" ссылается на класс с коллекцией. Это описано в устной форме, но с учетом характера отношений - для некоторых описание, которое, я думаю, может быть немного сложным, когда вы видите его первые несколько раз.
Как указано выше в исходном вопросе (вот как я наконец получил идею попробовать решение, на которое я наткнулся), примерный блок ниже кажется правильным способом to-many в OrmLite.
Кроме того, есть примечание о том, как класс коллектора должен быть установлен в класс элемента коллекции.
Вот основные шаги, которые необходимо выполнить:
а. В классе, который имеет коллекцию ( DomainItem в этом случае), аннотируйте поле коллекции следующим образом:
@ForeignCollectionField(eager = true)
В. В классе, который содержится в коллекции ( ContentItem в этом случае), вы должны иметь явную ссылку на родительский класс, содержащий коллекцию:
@DatabaseField(foreign = true)
protected DomainItem domainItem;
С. Перед сохранением ContentItem вы должны сохранить DomainItem в этом ContentItem, чтобы вернуть внешний ключ к DomainItem:
curContentItem.setDomainItem(curDomainItem);
contentItemDao.create(curContentItem);`
Я понял это, когда моя коллекция не извлекалась изначально. Я просмотрел таблицу для ContentItem, и DomainItem_id никогда не устанавливался там.
Пример:
public class DomainItem {
@DatabaseField(generatedId = true)
protected long id;
@ForeignCollectionField(eager = false)
protected ForeignCollection<ContentItem> contentItens;
// ...
}
public class ContentItem {
@DatabaseField(generatedId = true)
protected long id;
@DatabaseField(foreign = true)
protected DomainItem domainItem;
public void setDomainItem(DomainItem domainItem) {
this.domainItem = domainItem;
}
}