Могу ли я временно приостановить автоматически сгенерированный идентификатор в ORMLite? - PullRequest
0 голосов
/ 07 марта 2011

Я использую Android с ORMLite в небольшом приложении, которое сейчас пишу.Приложение стремится иметь работающую функцию импорта / экспорта, для которой я использую простую структуру XML.И все прекрасно работает, до определенного момента.

Ситуация следующая: Объект A содержит внешний ключ, ссылающийся на Объект B, который ссылается на Объект C через сам внешний ключ.Экспорт базы данных великолепен.Импорт работает с небольшой оговоркой, а именно с тем, что он работает до тех пор, пока идентификаторы всех объектов являются последовательными и начинаются с 1. Но если база данных фрагментирована, то есть я удалил запись здесь и там, после экспорта базы данных,У меня есть "дыры" в сгенерированной структуре XML.Примерами объектов могут быть:

@DatabaseTable("orders")
public class Order {
    @DatabaseField(generatedId = true)
    private int _id;
    @DatabaseField(columnName="date")
    private Date _date;
    @DatabaseField(columnName="cost")
    private double _cost;
    @DatabaseField(foreign = true, columnName="customer_id")
    private Customer _customer;
    // ... more fields, getters and setters
}

@DatabaseTable("customers")
public class Customer {
    @DatabaseField(generatedId = true);
    private int _id;
    @DatabaseField
    private String _name;
    // ... more fields, getters and setters
}

Допустим, у меня есть база данных с 2 клиентами (идентификаторы 1 и 2), которые содержат соответственно заказы с 1 по 5 и с 6 по 8. Экспорт этого и повторный импортв чистой базе данных работает отлично.Однако, если я удаляю клиента 1 и его заказы и экспортирую его, экспортер запишет их идентификатор, как он есть, то есть

<customer id="2">...</customer>

и

<order id="6">...</order>
<order id="7">...</order>
<order id="8">...</order>
<order id="9">...</order>

и т. Д.Когда я импортирую данные в новую базу данных, я сначала сохраню объект клиента с помощью

custDao.create((Customer)x);

, а затем каждый их заказ с помощью

orderDao.create((Order)o);

Проблема заключается в том, что функция createигнорирует предоставленный идентификатор (который не равен 0), а недавно сгенерированный идентификатор для клиента равен 1 (в новой пустой базе данных).То же самое для заказов.Но так как они ссылаются на клиента с id = 2, связь между ними разорвана.

Итак, после этого довольно многословного объяснения, у меня возникает вопрос: есть ли способ сказать ORMLite, чтобы оно взяло предоставленное значение дляполе generateId и работать с ним, а не перезаписывать его?Я был бы в порядке, если какое-либо Исключение генерируется в случае, если функция создания находит строку уже в таблице с тем же идентификатором, но в противном случае продолжит сохранение записи ... Я подумал об обходном пути: всеобъекты должны сортироваться по идентификатору с использованием интерфейса Comparator;сортировать ArrayList с объектами для импорта;для каждого объекта - считайте предполагаемый идентификатор в int, - сохраните в базе данных, используя dao.create, - если новый идентификатор объекта отличается от предполагаемого идентификатора, измените его с помощью dao.updateId, - перейдите к следующему объекту в списке.Но это кажется слишком громоздким и подверженным ошибкам: что если метод create попытается сгенерировать идентификатор, который вы только что переназначили для предыдущего объекта с помощью updateId?

Я не верю, что моя ситуация таковаредко, что никто не сталкивался с этим раньше.Буду признателен за решение!

С уважением, Тодор

1 Ответ

2 голосов
/ 07 марта 2011

ORMLite поддерживает опцию allowGeneratedIdInsert=true для аннотации @DatabaseField, которая позволяет вставлять объект с идентификатором, уже установленным в таблицу сгенерированного идентификатора.Если значение поля ID равно нулю или значение по умолчанию (0, ...), тогда база данных сгенерирует идентификатор.Это поддерживается не всеми типами баз данных (например, Derby).Вот еще одно обсуждение по этой конкретной теме.


Я действительно думаю, что здесь нужно построить граф объектов в памяти, связав собственно Customer на их Order объектах до сохранения их на диск.Если вы читаете своих клиентов в память, то читайте в Order объектах и ​​устанавливайте реальные Customer объекты для каждого из них.Когда вы затем создаете каждый объект Customer в базе данных, ORMLite изменит поле id на сгенерированное, которое изменит его на поле customer_id, сохраненное также в каждом Order.

Если у вас есть тонна данных и вы не можете прочитать все это в памяти за один раз (или по какой-то другой причине), тогда вы всегда можете создать Map<Integer,Integer> и сохранить идентификатор Customer из XML, сопоставленного с идентификатором, который вы получите.после того, как вы создадите его в базе данных.Затем, когда вы загружаете в Order объекты, вы можете установить новый исправленный идентификатор для постороннего объекта.

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

...