Создать таблицу с иностранным полем сбора
У меня есть этот абстрактный класс:
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' column-name не содержит внешнее поле класса br.com.project.model.PhytoterapicItem
2 ответа
Таким образом, сообщение об исключении было разработано, чтобы помочь здесь. Чтобы процитировать его с удаленными именами классов:
Иностранный коллекционный класс
ContentItem
для поляcontentItens
имя-столбца не содержит внешнего поля классаPhytoterapicItem
Это выглядит так. Всякий раз, когда у вас есть ForeignCollection
класс, содержащийся в коллекции, должен иметь внешнее поле, возвращаемое родительскому классу.
В твоем случае, PhytoterapicItem
расширяет DomainItem
класс, который имеет ForeignCollection
из ContentItem
объекты. Это означает, что ContentItem
должен иметь внешнее поле типа PhytoterapicItem
, В противном случае, как ORMLite узнает, какой из ContentItem
элементы в таблице связаны с определенным PhytoterapicItem
,
Пример Account
а также Order
объекты в иностранной коллекции документации могут помочь вам с вашей схемой. каждый Account
имеет зарубежную коллекцию Order
объекты. Всякий раз, когда вы запрашиваете Account
отдельный запрос выполняется, чтобы найти коллекцию Order
объекты, которые соответствуют определенному Account
, Это означает, что каждый Order
должен иметь иностранный Account
объект.
Мне потребовалось некоторое время, чтобы заметить / понять этот критический блок из документации ( http://ormlite.com/docs/foreign-collection):
Помните, что когда у вас есть поле ForeignCollection, класс в коллекции должен (в этом примере Order) должен иметь внешнее поле для класса, который имеет коллекцию (в этом примере Account). Если Учетная запись имеет иностранную коллекцию Приказов, то Заказ должен иметь внешнее поле Учетной записи. Это необходимо для того, чтобы ORMLite мог найти заказы, которые соответствуют определенной учетной записи.
Причина, по которой я был сбит с толку, заключается в том, что я не нашел ни одного примера кода (в документах или проектах примеров), где "содержащийся класс" ссылается на класс с коллекцией. Это описано в устной форме, но с учетом характера отношений - для некоторых описание, я думаю, может быть немного сложным, чтобы увидеть его, увидев его в первые несколько раз.
Как указано выше в исходном вопросе (именно так я наконец-то и решил попробовать решение, на которое наткнулся), приведенный ниже пример блока, кажется, является правильным способом сопоставления отношения коллекции один-ко-многим в OrmLite.
Кроме того, есть примечание о том, как класс держателя коллекции должен быть установлен в классе элемента коллекции.
Вот основные шаги, чтобы позаботиться о:
О. В классе, который имеет коллекцию (в данном случае DomainItem), аннотируйте поле коллекции следующим образом:
@ForeignCollectionField(eager = true)
Б. В классе, который содержится в коллекции (в данном случае ContentItem), у вас должна быть явная ссылка на родительский класс, который содержит коллекцию:
@DatabaseField(foreign = true)
protected DomainItem domainItem;
C. Перед сохранением 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;
}
}