<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Ross Attrill</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/ross_attrill/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/ross_attrill/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/ross_attrill//1168</id>
    <updated>2013-02-23T01:51:22Z</updated>
    <subtitle>A blog about the Perl programming language</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>DBIx::DataModel - Elegant Database Interaction with Perl</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/ross_attrill/2013/02/dbixdatamodel---elegant-database-interaction-with-perl.html" />
    <id>tag:blogs.perl.org,2013:/users/ross_attrill//1168.4368</id>

    <published>2013-02-23T01:21:23Z</published>
    <updated>2013-02-23T01:51:22Z</updated>

    <summary> DBIx::DataModel (DBIDM) is an Object Relational Mapper for Perl that is very elegant, simple and effective. It helps you to efficiently interact with your database. This article discusses three of the great features of DBIDM and how I find...</summary>
    <author>
        <name>Ross Attrill</name>
        
    </author>
    
    <category term="orm" label="ORM" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/ross_attrill/">
        <![CDATA[<p><a href="https://metacpan.org/module/DBIx::DataModel"> DBIx::DataModel </a> (DBIDM) is an Object Relational Mapper for Perl that is very elegant, simple and effective.  It helps you to efficiently interact with your database.</p>

<p>This article discusses three of the great features of DBIDM and how I find they help me to develop software more efficiently.  The three features discussed are:<br />
<ul><br />
	<li>results are hashes - so it is very easy to manipulate and debug query results,</li><br />
	<li>schema generation is fast, clean and effective - so we very quickly get a useful map within Perl of just the most important aspects of our database, and</li><br />
	<li>the API allows inserts, updates and selects to be defined extremely efficiently - keeping the easy things easy</li><br />
</ul><br />
The article also provides a very brief introduction to DBIDM and some notes on getting started with it.   There is also a rough example demonstrating how I combine DBIDM with Perl Dancer.</p>]]>
        <![CDATA[<h2>Introduction</h2>

<p>DBIDM is an Object Relational Mapping module that provides a Perl API for database operations such as SELECT, INSERT, UPDATE and DELETE.  DBIDM is similar to DBIx::Class (DBIC) and uses some of the same infrastructure such as <a href="https://metacpan.org/module/SQL::Translator">SQL::Translator</a> and <a href="https://metacpan.org/module/SQL::Abstract">SQL::Abstract</a>.</p>

<p>DBIDM relies on a schema mapping file that defines the most essential information about your database including tables, primary keys and foreign key relationships between tables.  This mapping file can be generated by hand or automatically by reverse engineering from your database.</p>

<p>Once you have your schema mapping place, DBIDM then provides a very efficient API to perform database selections, inserts, updates and deletion.   Complicated retrievals can be defined using Perl data structures since DBIDM builds in SQL::Abstract - which is the same SQL Abstraction engine as used by the widely used DBIC ORM.</p>

<p>The net result of all of this is that database interactions can now be coded extremely efficiently from within Perl.</p>

<h2>The Benefits of DBIDM</h2>

<p>With Perl, there is usually more than one way to do things and database interaction is no exception.  For example <br />
* <a href="https://metacpan.org/module/DBI">DBI</a> provides a rock solid, highly mature and proven API for database interactions using raw SQL<br />
* <a href="https://metacpan.org/module/DBIx::Simple">DBIx::Simple</a> provides an improved API on top of DBI for SQL coded interactions<br />
* <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a> provides a widely used and respected API for dealing with databases at a higher level of abstraction using Perl objects and methods</p>

<p>All of the various approaches have different costs and benefits - but for me DBIx::DataModel provides a pure Perl based API to my database without adding excessive complexity and overhead.</p>

<p>I will now describe three of the benefits that I see with DBIx::DataModel in terms of interacting with databases with Perl.</p>

<h4>1. Results are Hashes</h4>

<p>One of the most significant benefits that I find with DBIDM is that the results of select are just blessed arrays of hashes.</p>

<p>So if I just want to select all the rows from my table $name, using my schema connection $schema then I just do this:<br />
<pre><br />
my $rows = $schema->table($name)->select();<br />
</pre><br />
My $rows is now a reference to an array of hashes which I can immediately push through Data::Dumper to visualize, or send to my serializer.  In my context, I use DBIDM with Perl Dancer, so if I just return $rows at the end of my route handler, then Dancer automatically serializes my results as JSON.  It is important to note that $rows is a blessed reference, with two implications:<br />
a) DBIDM embeds additional functions that I can use with my results - such as an ability to automatically expand child records<br />
b) If your serializer (JSON) can't cope with blessed references then you must use the DBIDM provided unbless method prior to serialization </p>

<p>The benefit of results being simple Perl data structures is that I can manipulate the data using ordinary Perl - and I don't have to remember or look up any additional module specific methods to slice and dice my results.  This allows me to work more efficiently and makes my code simpler.</p>

<h4>2. Schema Generation is Fast, Efficient and Small</h4>

<p>When I am building new systems I design the database data-model first and then build my services layer on top of that.  As such, I want to set up my ORM schema mapping by reverse engineering from my database.</p>

<p>DBIDM does schema reverse engineering very efficiently via <a href="https://metacpan.org/module/DBIx::DataModel::Schema::Generator">DBIx::DataModel::Schema::Generator</a> which builds on top of <a href="https://metacpan.org/module/SQL::Translator">SQL::Translator</a>.</p>

<p>The result is a very tidy and contained schema mapping file containing a mapping of tables to objects, information about table primary keys and relationships between tables based on database foreign keys.   The schema file does not contain details of every database column / attribute nor any auto generated methods.</p>

<p>Because this schema mapping file is small and contained there are several benefits:<br />
* I don't end up with masses of auto generated mapping files and code inflating my code base<br />
* Everything I need to know about by database to schema mapping is easily found within one file<br />
* Schema generation is really fast - normally completing in a few seconds (compared to minutes for DBIC)</p>

<p>I find the speed benefit particulary important during the early phases of project design when I am often adding and modifying tables very quickly.</p>

<h4>3.  An efficient API for Selects, Inserts and Updates</h4>

<p>DBIDM provides a really efficient API for selects, inserts and updates.  I find that in many cases, database interactions become a single line of code.  This might be well demonstrated by example.  The following indicative code combines a dancer route that receives a POST of employee details and a service based on DBIDM to save those details to the database.</p>

<pre>
package MyPackage::EmployeeRoutes;
use Dancer ':syntax';

<p>use MyPackage::EmployeeService;</p>

<p>our $service = MyPackage::EmployeeService->new();</p>

<p>post '/employee' => sub {<br />
    my $hr = {  first_name => param('first_name'), <br />
                last_name  => param('last_name')};<br />
    my $id = $service->insert($hr);<br />
    return $id;<br />
};</p>

<p>package MyPackage::EmployeeService;</p>

<p>use Method::Signatures;<br />
use MyPackage::Schema;    # The DBIDM Schema</p>

<p>our $schema = MyPackage::Schema->singleton();<br />
our $dao = $schema->table('Employee');</p>

<p>method insert($hr) {<br />
    my $id = $dao->insert($hr);<br />
}<br />
</pre></p>

<p>In summary, the Dancer route unpacks the post parameters into a hash reference and the service inserts these details with a single line of code.  If I can be sure that the names of my post parameters match my database column names, this could be made even more efficient by getting the $hr from the Dancer 'params' method without explicitly specifying the post parameters.</p>

<p>The benefit to me as a developer is simple and efficient coding - labourious hand coded SQL INSERTs have been avoided.</p>

<h2>Getting Started with DBIDM</h2>

<p>DBIDM includes a very comprehensive set of quality documentation.  This documentation includes a quick start guide <br />
<a href="https://metacpan.org/module/DAMI/DBIx-DataModel-2.32/lib/DBIx/DataModel/Doc/Quickstart.pod">https://metacpan.org/module/DAMI/DBIx-DataModel-2.32/lib/DBIx/DataModel/Doc/Quickstart.pod</a> which may be helpful - particularly if you are happy to generate your schema by hand.   If you already have your database model in place and want to reverse engineer your DBIDM mapping from that, then make sure that you look at the <a href="https://metacpan.org/module/DBIx::DataModel::Schema::Generator">Schema Generator</a>.  I recommend that you install <a href="https://metacpan.org/module/Lingua::EN::Inflect">Lingua::EN::Inflect</a> - an optional dependency before using the schema generator - as it will ensure better quality plural names in the schema mapping file.</p>

<h2>Summary</h2>

<p>DBIDM is a fantastic piece of Perl software helping you interact with your database in a manner that is consistent with the Perl philosophy that easy things should be easy and hard things possible.</p>

<p>In this article I have described three of the key strengths of DBIDM being: <br />
<ul><br />
	<li>results as simple arrays of hashes;</li><br />
	<li>fast and efficient schema generation; and </li><br />
	<li>an elegant API for database interactions.</li><br />
</ul><br />
These are only some of the strengths of DBIDM and in a future article I hope to describe some more.</p>

<p>I can definitely recommend DBIDM as a great piece of software for interacting with your database using Perl.</p>

<h2>Acknowledgments</h2>

<p>DBIDM is provided to ther Perl community by <a href="https://metacpan.org/author/DAMI">Laurent Dami</a>.  Laurent is actively improving and supporting DBIDM.   I would like to thank Laurent for providing this excellent software.<br />
</p>]]>
    </content>
</entry>

</feed>
