<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>taichino.com &#187; sqlobject</title>
	<atom:link href="http://taichino.com/tag/sqlobject/feed" rel="self" type="application/rss+xml" />
	<link>http://taichino.com</link>
	<description>永遠のネバーランド</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:33:04 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>pythonのORMを色々試してみた</title>
		<link>http://taichino.com/engineer-life/database/1344</link>
		<comments>http://taichino.com/engineer-life/database/1344#comments</comments>
		<pubDate>Thu, 10 Dec 2009 22:10:15 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[elixir]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[sqlalchemy]]></category>
		<category><![CDATA[sqlobject]]></category>
		<category><![CDATA[storm]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1344</guid>
		<description><![CDATA[そろそろpythonでもSQLを直に書くのが面倒になってきたので、O/Rマッパーを探してみたところ、幾つか種類があったので有名どころを使ってみることにしました。今回試したのは以下の4つです。 SQLAlchemy SQLObject Elixir Storm まず用途についてですが、僕はテーブルスキーマはSQLで直に書きますので、ORMでDDLを扱うつもりはありません。DMLを簡単に扱いたいというのが一番の目標です。そこで予め作成して置いたテーブルに対してCRUD操作のし易さを比べてみました。比較に使用したのは以下のテーブルです。 CREATE TABLE `books` &#40; `id` INT&#40;11&#41; NOT NULL AUTO_INCREMENT, `title` VARCHAR&#40;100&#41; DEFAULT NULL, `price` INT&#40;11&#41; DEFAULT NULL, `isbn` INT&#40;11&#41; DEFAULT NULL, PRIMARY KEY &#40;`id`&#41;, UNIQUE KEY `isbn` &#40;`isbn`&#41; &#41; まず最初に試したのは、SQLAlchemyです。ちょっと検索した感じでは一番使われてそうな雰囲気です。早速使ってみたところ以下のようになりました。一連の初期化処理でセッションを作成し、セッションを通してオブジェクトの操作を行います。ソースを見ての通りCRUD操作自体は直感的に行えるのですが、マッピングを明示的に行う事や、セッションの管理やDBハンドルの管理などやや煩雑です。ただドキュメントを読む限りでは、非常に高機能で細やかな制御が行えるようです。感想としてはもう少しデータベースを隠蔽して欲しいと思いました。create_engineやget_session等は本来書きたい処理ではありません。 #!/usr/bin/python # -*- coding: utf-8 -*- &#160; import sys from sqlalchemy import * from sqlalchemy.orm import * &#160; # [...]]]></description>
			<content:encoded><![CDATA[<p>そろそろpythonでもSQLを直に書くのが面倒になってきたので、O/Rマッパーを探してみたところ、幾つか種類があったので有名どころを使ってみることにしました。今回試したのは以下の4つです。</p>
<ul>
<li> <a href="http://www.sqlalchemy.org/">SQLAlchemy </a></li>
<li> <a href="http://www.sqlobject.org/">SQLObject</a> </li>
<li> <a href="http://elixir.ematia.de/trac/">Elixir </a></li>
<li> <a href="https://storm.canonical.com/">Storm</a> </li>
</ul>
<p><span id="more-1344"></span></p>
<p>まず用途についてですが、僕はテーブルスキーマはSQLで直に書きますので、ORMでDDLを扱うつもりはありません。DMLを簡単に扱いたいというのが一番の目標です。そこで予め作成して置いたテーブルに対してCRUD操作のし易さを比べてみました。比較に使用したのは以下のテーブルです。</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`books`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`title`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`price`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`isbn`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`isbn`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`isbn`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>まず最初に試したのは、SQLAlchemyです。ちょっと検索した感じでは一番使われてそうな雰囲気です。早速使ってみたところ以下のようになりました。一連の初期化処理でセッションを作成し、セッションを通してオブジェクトの操作を行います。ソースを見ての通りCRUD操作自体は直感的に行えるのですが、マッピングを明示的に行う事や、セッションの管理やDBハンドルの管理などやや煩雑です。ただドキュメントを読む限りでは、非常に高機能で細やかな制御が行えるようです。感想としてはもう少しデータベースを隠蔽して欲しいと思いました。create_engineやget_session等は本来書きたい処理ではありません。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">orm</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># booksテーブルとマッピングするクラス</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, title, isbn=<span style="color: #008000;">None</span>, author=<span style="color: #008000;">None</span>, price=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #008000;">self</span>.<span style="color: black;">title</span>  = title
    <span style="color: #008000;">self</span>.<span style="color: black;">price</span>  = price
    <span style="color: #008000;">self</span>.<span style="color: black;">isbn</span>   = isbn
&nbsp;
<span style="color: #808080; font-style: italic;"># セッション(トランザクション)を取得する</span>
<span style="color: #ff7700;font-weight:bold;">def</span> get_session<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>:
  Session = sessionmaker<span style="color: black;">&#40;</span>bind=engine<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> Session<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  engine = create_engine<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mysql://root@localhost/sample'</span>, echo=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># echoでデバッグ出力</span>
  meta   = MetaData<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>
  books = Table<span style="color: black;">&#40;</span><span style="color: #483d8b;">'books'</span>, meta, autoload=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># autoloadでテーブル情報を自動ロードする</span>
  mapper<span style="color: black;">&#40;</span>Book, books<span style="color: black;">&#41;</span>
&nbsp;
  session = get_session<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># insert</span>
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    book1 = Book<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1Q84'</span>, price=<span style="color: #ff4500;">2000</span>,  isbn=<span style="color: #ff4500;">1234567</span><span style="color: black;">&#41;</span>
    book2 = Book<span style="color: black;">&#40;</span><span style="color: #483d8b;">'リアル9'</span>, price=<span style="color: #ff4500;">630</span>, isbn=<span style="color: #ff4500;">9876543</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">add</span><span style="color: black;">&#40;</span>book1<span style="color: black;">&#41;</span>
    session.<span style="color: black;">add</span><span style="color: black;">&#40;</span>book2<span style="color: black;">&#41;</span>
    session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">exc_info</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># duplicate error</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># select</span>
  session = get_session<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> b
&nbsp;
  <span style="color: #808080; font-style: italic;"># update</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    b.<span style="color: black;">price</span> <span style="color: #66cc66;">*</span>= <span style="color: #ff4500;">1.05</span>
  session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>   <span style="color: #808080; font-style: italic;"># just modify object's value and commit</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># delete</span>
  session = get_session<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> b.<span style="color: black;">price</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">2000</span>:
      session.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#41;</span>
  session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
  main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>次に試してみたのがSQLObjectです。同じ処理を書いたコードが以下になります。SQLAlchemyと比べてとてもシンプルにまとまっています。セッション周りの煩雑なコードも不要ですし、またテーブル名を指定するだけで、自動的にカラムをロードしてくれるのも便利です。イメージしていたORMとかなり近く、もうこれで良いかなと思ったのですが、１つ気になる情報がありました。TurboGearsというWebフレームワークがバージョン1.xの際に採用していたSQLObjectを、2.xからSQLAlchemyに差し替えた事です。どうも複雑なデータベースを操作する際のパフォーマンスに問題があるというのが理由だそうです。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> sqlobject <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 他の処理に先立ってconnectionを作っておく必要がある</span>
sqlhub.<span style="color: black;">processConnection</span> = connectionForURI<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mysql://root@localhost/sample?debug=1'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># booksテーブルにマッピングするオブジェクト</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>SQLObject<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">class</span> sqlmeta:
    table        = <span style="color: #483d8b;">&quot;books&quot;</span>
    fromDatabase = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  <span style="color: #808080; font-style: italic;"># insert</span>
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    book1 = Book<span style="color: black;">&#40;</span>title=<span style="color: #483d8b;">'1Q84'</span>,   price=<span style="color: #ff4500;">2000</span>, isbn=<span style="color: #ff4500;">1234567</span><span style="color: black;">&#41;</span>
    book2 = Book<span style="color: black;">&#40;</span>title=<span style="color: #483d8b;">'リアル9'</span>, price=<span style="color: #ff4500;">630</span>,  isbn=<span style="color: #ff4500;">9876543</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">exc_info</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># duplicate</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># select</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> b.<span style="color: black;">title</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># update</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    b.<span style="color: black;">price</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>b.<span style="color: black;">price</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">1.05</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># delete</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> b.<span style="color: black;">price</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">2000</span>:
      Book.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>b.<span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
  main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>正直DBのパフォーマンスが問題になるようなアプリケーションは、まだ作れないのでSQLObjectでも良かったのですが、念のため他のORMを見ていると今度はElixirというモジュールが見つかりました。これはSQLAlchemyのラッパーで、乱暴な言い方をすればSQLAlchemyをSQLObjectの様に扱えるようになります。実際のコードは以下になります。マッピングが自動化されて、セッション管理なども簡潔に記述できるようになっています。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> elixir <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
metadata.<span style="color: black;">bind</span> = <span style="color: #483d8b;">'mysql://root@localhost/sample'</span>
metadata.<span style="color: black;">bind</span>.<span style="color: black;">echo</span> = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># booksテーブルにマッピングするオブジェクト</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>Entity<span style="color: black;">&#41;</span>:
  using_options<span style="color: black;">&#40;</span>tablename=<span style="color: #483d8b;">'books'</span>, autoload=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  setup_all<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># insert </span>
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    book1 = Book<span style="color: black;">&#40;</span>title=<span style="color: #483d8b;">'1Q84'</span>,   price=<span style="color: #ff4500;">2000</span>, isbn=<span style="color: #ff4500;">1234567</span><span style="color: black;">&#41;</span>
    book2 = Book<span style="color: black;">&#40;</span>title=<span style="color: #483d8b;">'リアル9'</span>, price=<span style="color: #ff4500;">600</span>,  isbn=<span style="color: #ff4500;">9876543</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">exc_info</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  session.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># select</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: black;">query</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> b
&nbsp;
  <span style="color: #808080; font-style: italic;"># update</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: black;">query</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    b.<span style="color: black;">price</span> <span style="color: #66cc66;">*</span>= <span style="color: #ff4500;">1.05</span>
  session.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># delete</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> Book.<span style="color: black;">query</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> b.<span style="color: black;">price</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">2000</span>:
      b.<span style="color: black;">delete</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  session.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
  main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>これはもうElixirで決まりと思ったのですが、ウノウラボのブログに「<a href="http://labs.unoh.net/2008/04/pythonorm1.html">PythonのORMを研究してみる(1) </a>」という記事があり、そこでSQLAlchemyやSQLObjectが選択肢にある中でStormを紹介しますと言っているのが気になって、Stormでも書いてみました。以下がソースになります。オブジェクトのコンストラクタを自分で書かないと駄目なのが気になります。また僕の使い方が良くないのか、データベースに登録された日本語が化けてしまいました。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> storm.<span style="color: #008000;">locals</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> storm.<span style="color: black;">tracer</span> <span style="color: #ff7700;font-weight:bold;">import</span> debug
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  __storm_table__ = <span style="color: #483d8b;">'books'</span>
  <span style="color: #008000;">id</span>    = Int<span style="color: black;">&#40;</span>primary=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
  title = Unicode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  price = Int<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  isbn  = Int<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, title, price, isbn<span style="color: black;">&#41;</span>:
    <span style="color: #008000;">self</span>.<span style="color: black;">title</span> = title
    <span style="color: #008000;">self</span>.<span style="color: black;">price</span> = price
    <span style="color: #008000;">self</span>.<span style="color: black;">isbn</span>  = isbn
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  debug<span style="color: black;">&#40;</span><span style="color: #008000;">True</span>, stream=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span><span style="color: black;">&#41;</span>
  db = create_database<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mysql://root@localhost/sample'</span><span style="color: black;">&#41;</span>
  store = Store<span style="color: black;">&#40;</span>db<span style="color: black;">&#41;</span>
&nbsp;
  book1 = Book<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'1Q84'</span>, <span style="color: #ff4500;">2000</span>, <span style="color: #ff4500;">123456</span><span style="color: black;">&#41;</span>
  book2 = Book<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'リアル'</span>, <span style="color: #ff4500;">600</span>, <span style="color: #ff4500;">987654</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># insert </span>
  <span style="color: #ff7700;font-weight:bold;">try</span>:
    store.<span style="color: black;">add</span><span style="color: black;">&#40;</span>book1<span style="color: black;">&#41;</span>
    store.<span style="color: black;">add</span><span style="color: black;">&#40;</span>book2<span style="color: black;">&#41;</span>
    store.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">except</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">exc_info</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    store.<span style="color: black;">rollback</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># select</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> store.<span style="color: black;">find</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> b
&nbsp;
  <span style="color: #808080; font-style: italic;"># update</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> store.<span style="color: black;">find</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>:
    b.<span style="color: black;">price</span> <span style="color: #66cc66;">*</span>= <span style="color: #ff4500;">1.05</span>
  store.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># delete</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> store.<span style="color: black;">find</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> b.<span style="color: black;">price</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">2000</span>:
      store.<span style="color: black;">remove</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#41;</span>
  store.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
  main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><strong>まとめ</strong><br />
というわけでまとめですが、上の４つでいうとElixirかSQLObjectが使い易いと思いました。オブジェクトとテーブルの自動マッピングが出来るのでコード量がかなり減ります。どちらを使うか迷うのですが、総合判断でElixirを使う事にしました。いざという時にSQLAlchemyの機能にアクセスできるのが、何となく安心だというのが理由です。</p>
<table border="1" style="text-align:center">
<tr>
<th>ORM</th>
<th>サンプルコードの行数</th>
<th>使い心地</th>
<th>ドキュメント</th>
</tr>
<tr>
<td>SQLAlchemy</td>
<td>56</td>
<td>△</td>
<td>◎</td>
</tr>
<tr>
<td>SQLObject</td>
<td>38</td>
<td>◎</td>
<td>◯</td>
</tr>
<tr>
<td>Elixir</td>
<td>42</td>
<td>◯</td>
<td>◯</td>
</tr>
<tr>
<td>Storm</td>
<td>53</td>
<td>△</td>
<td>△</td>
</tr>
</table>
<p>本来ならベンチマークを入れるべきところですが、それは又の機会という事で。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/engineer-life/database/1344/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

