简体   繁体   中英

Perl DBIx::Class transactions with missing commit

I struggle with a inconsistent behavior of the Perl DBIx::Class module. I have written a simple pure Perl class, which defines the class member 'schema', which is just a reference to a pre initialized/connected DBIx::Class::Schema object and a method to add some data to the database:

sub new {
    my $class = shift;
    my $params;
    if(1 == scalar @_ && 'HASH' eq ref($_[0])) {
        $params = shift;
    } else {
        my %params = @_;
        $params = \%params;
    }

    my $self = {
        schema => $params->{schema}
    };

    bless $self, $class;

    return $self;
}


sub addToQueue {
    my $self = shift;
    my $params;
    if(1 == scalar @_ && 'HASH' eq ref($_[0])) {
        $params = shift;
    } else {
        my %params = @_;
        $params = \%params;
    }
    
    #some parameter constraints checks
    ....
    
    $self->{schema}->txn_do(sub {
        $self->{schema}->resultset('SOME_QUEUE')->create($params);
    });

    # this row is necessary if this method is called from programs, which uses moose
    $self->{schema}->txn_commit();
 
    return;
}

If I call the method addToQueue from one Perl (uses Moose) program, I have to add the code row

self->{schema}->txn_commit();

to really trigger the DB commit command. If I call the method from another Perl programm (does not use Moose) the code fails with the message:

Use of uninitialized value $msg in substitution (s///) at /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm line 58. Use of uninitialized value $msg in concatenation (.) or string at /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm line 68. DBIx::Class::Storage::txn_commit(): Refusing to commit without a started transaction

If I remove the duplicated commit command, it works for the non Moose program, but the Moose using program omits the commit and the created entry will not be written to the database.

Does anybody knows these issue?

From the documentation for txn_do ,

WARNING: If you are connected with AutoCommit => 0 the transaction is considered nested, and you will still need to call "txn_commit" to write your changes when appropriate. You will also want to connect with auto_savepoint => 1 to get partial rollback to work, if the storage driver for your database supports it.

Connecting with AutoCommit => 1 is recommended.

I suspect you are using AutoCommit => 0 when you need the extra txn_commit .

The short answer is: you're committing the transaction twice. txn_do automatically commits when leaving the block when no exception is thrown. Please post an code example that loads Moose and the log from DBIC_TRACE=1 which shows that no commit is triggered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM