Как я могу сделать обновление в Class :: DBI без предварительного выбора записи? - PullRequest
6 голосов
/ 04 февраля 2009

Чтобы выполнить вставку с помощью 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 ]

6 голосов
/ 04 февраля 2009

Насколько я знаю, 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 .

4 голосов
/ 04 февраля 2009

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

...