5

要使用 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,然后执行 UPDATE 而不是仅执行一次 UPDATE。

Class::DBI 有没有更好的方法来做到这一点?我不想做 42 $object->a(1), $object->b(2), etc., $object->update;

4

2 回答 2

6

据我所知,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::ObjectDBIx::Class )肯定会更好。DBIx::Class 甚至包括一个 Class::DBI 兼容层

于 2009-02-04T13:43:39.887 回答
4

我发现这样做的一种方法是覆盖对象的默认迭代器类。这允许您使用集合上的更新方法来拥有单个对象的集合。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在 update() 发生时将该方法投入使用。它将通过不更新未更改的行来帮助您节省时间。

于 2009-02-04T14:33:00.380 回答