Внешний ключ Android OrmLite / внешняя коллекция

В моем недавнем проекте на Android я использую OrmLite для моделирования отношений «один ко многим», а также простых отношений «один к одному». Я заметил, что при отношениях «один ко многим» дочерний элемент содержит ссылку внешнего ключа на родителя в базе данных. Тем не менее, при загрузке родительского объекта OrmLite знает, что делать, и загружает коллекцию дочерних элементов, что, конечно же, является желаемым поведением.

Однако с простыми отношениями «один к одному» родительский объект, по-видимому, должен содержать столбец внешнего ключа, чтобы добиться того же поведения.

Итак, фактический вопрос: возможно ли, чтобы OrmLite загружал дочерние объекты в отношениях один к одному, когда внешний ключ установлен только в дочернем элементе, поскольку это стандартное поведение с отношениями один ко многим?

Вот пример кода:

@DatabaseTable
public class Parent
{  

@DatabaseField(foreign = true)
private Child1 child1;

@ForeignCollectionField
private Collection<Child2> children2;

}

Итак, в дочерних 1 и 2 мне нужно иметь ссылку на родителя следующим образом:

 public class Child1 / Child2
{       

    @DatabaseField(foreign = true)
    private Parent parent;
}

Поэтому при сохранении ребенка2 я просто устанавливаю

child2.setParent(parent);
child2Dao.create(child2)

Но чтобы получить такое же поведение при запросе родителя, включая дочерний элемент1 и дочерний элемент2, мне пришлось бы сохранять отношения наоборот:

parent.setChild1(child1)
parentDao.create(parent)

Это очень неудобно, так как я хочу, чтобы либо child1/child2 содержали внешний ключ родителя, либо наоборот. Но смесь кажется несколько некрасивой!

Есть идеи, как этого добиться?

Я искал ответы на этот вопрос здесь, но не нашел. Если это дубликат, извините!

Большое тебе спасибо!

Редактировать:

Точнее: можно ли установить внешний ключ в моей таблице child1 и по-прежнему иметь возможность получить child1 при запросе Parent. ORMLite делает это автоматически для чужой коллекции child2. Я хочу такого же поведения для ребенка1. Но когда я установил

child1.setParent(parent);
child1Dao.create(child1);

а потом сделать запрос

Parent parent = parentDao.queryForId(1)

получается только дочерний элемент2, поскольку в родительской таблице нет ссылки (внешнего ключа) на дочерний элемент1. Только child1 имеет ссылку на родителя.

Итак: я хочу, чтобы OrmLite автоматически обновлял родительский столбец внешнего ключа или говорил Ormlite по-прежнему получать дочерний элемент1, даже если в родительском элементе не установлен внешний ключ (как это именно в случае с коллекцией дочерних2). Это как-то возможно? Или нет?

Я надеюсь, что это не слишком запутанно :) Я полностью понимаю, что было бы проще просто установить внешний ключ в родительском элементе. Но мне очень не нравится такой подход, так как у некоторых детей будет внешний ключ родителя, а у некоторых нет.

Большое Вам спасибо


person Al Cabone    schedule 31.03.2017    source источник


Ответы (2)


ORMLite поддерживает концепцию «чужих» объектов, когда одно или несколько полей, соответствующих объекту, сохраняются в другой таблице той же базы данных. Например, если в вашей базе данных есть объекты «Заказ», и каждый заказ имеет соответствующий объект «Учетная запись», то объект «Заказ» будет иметь поле внешней учетной записи. С посторонними объектами только поле идентификатора из учетной записи сохраняется в таблице заказов в виде столбца «account_id». Например, класс Order может выглядеть примерно так:

@DatabaseTable(tableName = "orders")
public class Order {

    @DatabaseField(generatedId = true)
    private int id;

    @DatabaseField(canBeNull = false, foreign = true)
    private Account account;
    …
}

При создании таблицы Order будет сгенерирован что-то вроде следующего SQL:

CREATE TABLE `orders`
   (`id` INTEGER AUTO_INCREMENT , `account_id` INTEGER,
    PRIMARY KEY (`id`)); 

Когда вы создаете поле с посторонним объектом, обратите внимание, что посторонний объект не будет создан для вас автоматически. Если ваш внешний объект имеет сгенерированный идентификатор, который предоставляется базой данных, вам необходимо создать его, прежде чем создавать какие-либо объекты, которые на него ссылаются. Например:

Account account = new Account("Jim Coakley");
accountDao.create(account);
// this will create the account object and set any generated ids

// now we can set the account on the order and create it
Order order = new Order("Jim Sanders", 12.34);
order.setAccount(account);
…
orderDao.create(order);

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

public class Account {
    …
    @ForeignCollectionField(eager = false)
    ForeignCollection<Order> orders;
    …
}

В приведенном выше примере аннотация @ForeignCollectionField отмечает, что поле заказов представляет собой набор заказов, соответствующих учетной записи. Тип поля заказов должен быть либо ForeignCollection, либо Collection — никакие другие коллекции не поддерживаются, поскольку они намного тяжелее и поддерживают множество методов.

Источник: http://ormlite.com/

person Luiz Fernando Salvaterra    schedule 31.03.2017
comment
Большое спасибо за ваш быстрый ответ! Я полностью осведомлен об основных функциях ORM, поскольку я исходил из фона структуры сущности MS. Кажется, я не очень ясно выразился в своем вопросе, я постараюсь обновить. - person Al Cabone; 01.04.2017
comment
Поэтому, пожалуйста, взгляните на Edit. На самом деле мне, вероятно, понадобится что-то вроде @ForeignField (которого, как я полагаю, не существует в OrmLite), который не хранит внешний ключ, НО сообщает ORMLite, чтобы он включал порядок (дочерний) при запросе учетной записи (родительский) - person Al Cabone; 01.04.2017

Согласно документации ORMLite, DatabaseField по умолчанию с canBeNull = true. Таким образом, нет необходимости устанавливать Parent при создании Child1. Чтобы получить дочерние элементы в родительском и наоборот, вы можете установить ForeignAutoRefresh = true.

Если вы хотите оставить столбец внешнего ключа только в одной таблице, возможно, вы можете добиться этого, установив maxForeignAutoRefreshLevel = 1.

person Alexandre    schedule 31.03.2017
comment
Спасибо за ваш ответ! К сожалению, это не то, что я искал. Я знаю иностранный авторефреш, но мой вопрос направлен в другую сторону. Я обновлю свой вопрос. - person Al Cabone; 01.04.2017
comment
Я понял ваш вопрос. Я также не нашел ответа в документации ORMLite, вы можете попробовать отправить свой вопрос команде разработчиков ORMLite. - person Alexandre; 01.04.2017