Как я могу сделать обновление в Class::DBI без предварительного выбора записи?
Чтобы сделать вставку с Class::DBI, вы можете просто сделать:
my $object = Object::DB->insert({ a => 1, b => 2, c => 3, ...});
Но нет такой вещи для обновления. Лучшее, что я мог придумать, это сначала выбрать запись, а затем обновить ее:
my $object = Object::DB->retrieve($id);
my $object->set( a => 1, b => 2, c => 3, ...};
$object->update;
Это неэффективно, так как я должен сначала сделать SELECT, а затем ОБНОВЛЕНИЕ вместо одного ОБНОВЛЕНИЯ.
Есть ли лучший способ сделать это с Class::DBI? Я не хочу делать 42 $object->a(1), $object->b(2) и т. Д., $ Object->update;
2 ответа
Насколько я знаю, Class::DBI не имеет хорошего способа сделать это, как вы заметили, его update()
Метод предназначен для вызова объекта, который был предварительно загружен из базы данных.
Однако вы можете убедить Class:: DBI сделать то, что вы хотите, примерно так:
# Make new "empty" object
my $o = My::CDBI::Object->new;
# Set the primary key column and discard the change
$o->set(your_pk_column => 123);
$o->discard_changes;
# Set your other columns
$o->set(a => 'foo', b => 'bar');
# Do the update
$o->update;
Если эта функция важна для вас, и вы еще не слишком углубились в свой проект, вам определенно повезет с одним из новых Perl ORM, таким как Rose::DB::Object или DBIx:: Class. DBIx:: Class даже включает в себя уровень совместимости Class:: DBI.
Один из способов сделать это - переопределить класс итераторов по умолчанию для ваших объектов. Это позволяет вам иметь коллекцию отдельных объектов с методом обновления в коллекции. Class::DBI предоставляет метод для этого:
__PACKAGE__->iterator_class('MyClass::CDBI::Iterator');
Это позволяет вам сделать update
метод в классе итератора, который может сохранить все объекты в коллекции. Таким образом, ваш код может выглядеть примерно так:
my $collection = Object::DB->search_where({id => {'>=', 0}});
foreach my $obj ($collection->next()) {
$obj->a('bob');
$obj->b('tom');
}
$collection->update();
Что делает некоторый довольно хорошо документированный код. Если вы пойдете по этому пути, я бы также предложил поставить is_changed
метод в использовании, поскольку происходит обновление (). Это поможет вам сэкономить время, не обновляя неизмененные строки.