如何在不先选择记录的情况下在 Class::DBI 中进行更新?

发布于 2024-07-13 15:51:54 字数 502 浏览 7 评论 0原文

要使用 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) 等,$object->update;

To do an insert with Class::DBI, you can simply do:

my $object = Object::DB->insert({ a => 1, b => 2, c => 3, ...});

But there is no such thing for update. The best I could come up with is selecting the record first then updating it:

my $object = Object::DB->retrieve($id);
my $object->set( a => 1, b => 2, c => 3, ...};
$object->update;

This is not efficient since I have to do a SELECT first, and then an UPDATE instead of just one UPDATE.

Is there a better way to do this with Class::DBI? I don't want to do 42 $object->a(1), $object->b(2), etc., $object->update;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对风讲故事 2024-07-20 15:51:55

据我所知, 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 或 < a href="http://www.perlfoundation.org/perl5/index.cgi?dbix_class" rel="nofollow noreferrer">DBIx::Class。 DBIx::Class 甚至包括 a Class::DBI 兼容性层

As far as I know, Class::DBI does not have a good way to do this, As you've noted, its update() method is meant to be called on an object that has been previously loaded from the database.

You may be able to convince Class::DBI to do what you want, however, with something like this:

# 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;

If this feature is important to you and you're not already too far into your project, you will definitely have better luck with one of the newer Perl ORMs such as Rose::DB::Object or DBIx::Class. DBIx::Class even includes a Class::DBI compatibility layer.

冰葑 2024-07-20 15:51:55

我发现执行此操作的一种方法是覆盖对象的默认迭代器类。 这允许您拥有单个对象的集合,并在集合上使用更新方法。 Class::DBI 为此提供了一个方法:

__PACKAGE__->iterator_class('MyClass::CDBI::Iterator');

这允许您在迭代器类中创建一个更新方法,该方法可以保存集合中的所有对象。 因此,您的代码可能看起来像这样:

my $collection = Object::DB->search_where({id => {'>=', 0}});
foreach my $obj ($collection->next()) {
  $obj->a('bob');
  $obj->b('tom');
}
$collection->update();

这使得一些非常好的自我记录代码。 如果您走这条路,我还建议在 update() 发生时使用 is_changed 方法。 它将通过不更新未更改的行来帮助您节省时间。

One way that I've found to do this is to override the default iterator class for your objects. This allows you to have a collection of individual objects with an update method on the collection. Class::DBI provides an method for this:

__PACKAGE__->iterator_class('MyClass::CDBI::Iterator');

This allows you to then make an update method in the iterator class that can save all of the objects in the collection. As such your code may look something like this:

my $collection = Object::DB->search_where({id => {'>=', 0}});
foreach my $obj ($collection->next()) {
  $obj->a('bob');
  $obj->b('tom');
}
$collection->update();

Which makes for some pretty well self-documented code. If you go this route, I'd also suggest putting the is_changed method into use as the update() occurs. It will help you save time by not updating unchanged rows.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文