异常发生时如何访问数据库数据?

时间:2017-10-21 14:32:18

标签: perl dbi dbix-class

我有下一个代码:

my $savepoint =  $c->db->txn_scope_guard;
return $self->render( 'subnet/create',  error => [ create => $@ ],
    servers =>  $self->rows( 'Server' )->lookup,
) unless $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) };
$savepoint->commit;

这里rows是Mojolicious帮助程序,它提供对数据的访问。

sub model {
    my( $c, $table_name ) =  (shift,shift);

    return $c->db->resultset( $table_name );
}

->db也是帮手:

sub db { return $schema
    //=  DBIx::Class::Schema->connect( $DB->{ DSN },  @$DB{ qw/ USER PASS / },  {
        AutoCommit => 1,
        RaiseError => 1,
        quote_char => '"',
    })
});

当我创建$subnet并且发生了唯一约束时(这里无论发生了哪种约束,实际上是在任何异常的情况下)我得到了错误:

DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR:  current transaction is aborted, commands ignored until end of transaction block [for Statement "SELECT "me"."id", "me"."hostname" FROM "servers" "me" ORDER BY hostname"] at ...

这是当我用eval{ ... }捕获异常时当前事务被中止而我无法$self->rows( 'Server' )->lookup

是否有办法在发生异常后访问服务器数据?

1 个答案:

答案 0 :(得分:0)

似乎我找到了答案,因为更仔细地阅读错误信息:

  

...命令被忽略,直到事务块结束

因此,当异常发生时,我强制结束事务块:

$c->db->txn_rollback;

代码:

my $savepoint =  $c->db->txn_scope_guard;
unless( $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) } ) {
    my $e = $@; # $@ may be changed before `create => $@`
    undef $savepoint; # Or the same: $c->db->txn_rollback;     
    return $self->render( 'subnet/create',  error => [ create => $e ],
        servers =>  $self->rows( 'Server' )->lookup,
    );
}
$savepoint->commit;