The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

DBIx::Mint - A mostly class-based ORM for Perl

VERSION

This documentation refers to DBIx::Mint 0.071

SYNOPSIS

Define your classes, which will play the role DBIx::Mint::Table:

 package Bloodbowl::Team;
 use Moo;
 with 'DBIx::Mint::Table';
 
 has id   => (is => 'rw' );
 has name => (is => 'rw' );
 ...

Nearby (probably in a module of its own), you define the schema for your classes:

 package Bloodbowl::Schema;

 my $schema = DBIx::Mint->instance->schema;
 $schema->add_class(
     class      => 'Bloodbowl::Team',
     table      => 'teams',
     pk         => 'id',
     auto_pk    => 1,
 );
 
 $schema->add_class(
     class      => 'Bloodbowl::Player',
     table      => 'players',
     pk         => 'id',
     auto_pk    => 1,
 );
 
 # This is a one-to-many relationship
 $schema->one_to_many(
     conditions     => 
        ['Bloodbowl::Team', { id => 'team'}, 'Bloodbowl::Player'],
     method         => 'get_players',
     inverse_method => 'get_team',
 );

And in your your scripts:

 use DBIx::Mint;
 use My::Schema;
 
 # Connect to the database
 DBIx::Mint->connect( $dsn, $user, $passwd, { dbi => 'options'} );
 
 my $team    = Bloodbowl::Team->find(1);
 my @players = $team->get_players;
 
 # Database modification methods include insert, update, and delete.
 # They act on a single object when called as instance methods
 # but over the whole table if called as class methods:
 $team->name('Los Invencibles');
 $team->update;
 
 Bloodbowl::Coach->update(
    { status   => 'suspended' }, 
    { password => 'blocked' });
 

Declaring the schema allows you to modify the data. To define a schema and to learn about data modification methods, look into DBIx::Mint::Schema and DBIx::Mint::Table.

If you only need to query the database, no schema is needed. DBIx::Mint::ResultSet objects build database queries and fetch the resulting records:

 my $rs = DBIx::Mint::ResultSet->new( table => 'coaches' );
 
 # You can perform joins:
 my @team_players = $rs->search( { 'me.id' => 1 } )
   ->inner_join( 'teams',   { 'me.id'    => 'coach' })
   ->inner_join( 'players', { 'teams.id' => 'team'  })
   ->all;
 

DESCRIPTION

DBIx::Mint is a mostly class-based, object-relational mapping module for Perl. It tries to be simple and flexible, and it is meant to integrate with your own custom classes.

Since version 0.04, it allows for multiple database connections and it features DBIx::Connector objects under the hood. This should make DBIx::Mint easy to use in persistent environments.

There are many ORMs for Perl. Most notably, you should look at DBIx::Class and DBIx::DataModel which are two robust, proven offerings as of today. DBIx::Lite is another light-weight alternative.

DOCUMENTATION

The documentation is split into four parts:

  • This general view, which documents the umbrella class DBIx::Mint. A DBIx::Mint object encapsulates a given database conection and its schema.

  • DBIx::Mint::Schema documents the mapping between classes and database tables. It shows how to specify table names, primary keys and how to create associations between classes.

  • DBIx::Mint::Table is a role that allows you to modify or fetch data from a single table. It is meant to be applied to your custom classes using Moo or Role::Tiny::With.

  • DBIx::Mint::ResultSet performs database queries using chainable methods. It does not know about the schema, so it can be used without one or without any external classes .

GENERALITIES

The basic idea is that, frequently, a class can be mapped to a database table. Records become objects that can be created, fetched, updated and deleted. With the help of a schema, classes know what database table they represent, as well as their primary keys and the relationships they have with other classes. Relationships between classes are represented as methods that act upon objects from other classes, for example, or that simply return data. Using such a schema and a table-accessing role, classes gain database persistence.

Fetching data from joined tables is different, though. While you can have a class to represent records comming from a join, you cannot create, update or delete directly the objects from such a class. Using DBIx::Mint::ResultSet objects, complex table joins and queries are encapsulated, along with different options to actually fetch data and possibly bless it into full-blown objects. In this case, DBIx::Mint uses the result set approach, as DBIx::Lite does.

Finally, DBIx::Mint objects contain the database connection, the database schema and its SQL syntax details. Because each object encapsulates a database connection, you may create several objects to interact with different databases within your program. Mint objects are kept in a centralized pool so that they remain accessible without the need of passing them through explicitly.

SUBROUTINES/METHODS IMPLEMENTED BY DBIx::Mint

new

First of three constructors. All of them will save the newly created object into the connection pool, but they will croak if the object exists already. All the arguments to new are optional. If abstract or connector are not given, the objects will be created for you with their default arguments.

name

The name of the new Mint object. Naming your objects allows for having more than one, and thus for having simultaneus connections to different databases. The object name will be used to fetch it from the connections pool (see the method DBIx::Mint::instance).

schema

A DBIx::Mint::Schema object. You can create the DBIx::Mint::Schema yourself and feed it into different DBIx::Mint objects to use the same schema over different databases.

abstract

A SQL::Abstract::More object.

connector

A DBIx::Connector object.

connect

Connects the Mint object to the database. If called as a class method, connect creates a Mint object with the default name first. It receives your database connection parameters per DBI's specifications:

 # Create the default Mint object and its connection:
 DBIx::Mint->connect('dbi:SQLite:dbname=t/bloodbowl.db', $username, $password,
        { AutoCommit => 1, RaiseError => 1 });

 # Create a named connection:
 my $mint = DBIx::Mint->new( name => 'other' );
 $mint->connect('dbi:SQLite:dbname=t/bloodbowl.db', '', '',
        { AutoCommit => 1, RaiseError => 1 });

instance

Class method. It fetches an instance of DBIx::Mint from the object pool:

 my $mint  = DBIx::Mint->instance;           # Default connection
 my $mint2 = DBIx::Mint->instance('other');  # 'other' connection

If the object does not exist, it will be created and so this is the third constructor. This method allows you to create mappings to different databases in the same program. The optional argument is used as the DBIx::Mint object name.

connector

This accessor/mutator will return the underlying DBIx::Connector object.

dbh

This method will return the underlying database handle, which is guaranteed to be alive.

abstract

This is the accessor/mutator for the SQL::Abstract::More subjacent object.

schema

This is the accessor/mutator for the DBIx::Mint::Schema instance.

do_transaction

This instance method will take a code reference and execute it within a transaction block. In case the transaction fails (your code dies) it is rolled back and a warning is thrown. In this case, do_transaction will return undef. If successful, the transaction will be commited and the method will return a true value.

 $mint->do_transaction( $code_ref ) || die "Transaction failed!";

Note that it must be called as an intance method, not as a class method.

USE OF DBIx::Connector

Under the hood, DBIx::Mint uses DBIx::Connector to hold the database handle and to make sure that the connection is well and alive when you need it. The database modification routines employ the 'fixup' mode for modifying the database at a very fine-grained level, so that no side-effects are visible. This allows us to use DBIx::Connector in an efficient way. If you choose to install method modifiers around database interactions, be careful to avoid unwanted secondary effects.

The query routines offered by DBIx::Mint::ResultSet use the 'fixup' mode while retrieving the statement holder with the SELECT query already prepared, but not while extracting information in the execution phase. If you fear that the database connection may have died in the meantime, you can always use Mint's connector method to get a hold of the DBIx::Connector object and manage the whole query process yourself. This should not be necessary, though.

DEPENDENCIES

This distribution depends on the following external, non-core modules:

Moo
MooX::Singleton
SQL::Abstract::More
DBI
DBIx::Connector
List::MoreUtils
Clone

BUGS AND LIMITATIONS

Testing is not complete; in particular, tests look mostly for the expected results and not for edge cases or plain incorrect input.

Please report problems to the author. Patches are welcome. Tests are welcome also.

ACKNOWLEDGEMENTS

The ResultSet class was inspired by DBIx::Lite, by Alessandro Ranellucci.

AUTHOR

Julio Fraire, <julio.fraire@gmail.com>

LICENCE AND COPYRIGHT

Copyright (c) 2015, Julio Fraire. All rights reserved.

LICENSE

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.