Как я могу сделать обновление в 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 метод в использовании, поскольку происходит обновление (). Это поможет вам сэкономить время, не обновляя неизмененные строки.

Другие вопросы по тегам