SlideShare a Scribd company logo
SQLマッピングフレームワーク
「Kobati」のはなし
南谷千城
2015/02/27
内容
• Kobatiの概要
• Kobatiの使い方
• 実装の説明スライド無し
• 新規インストールした環境では動かない
– XPathライブラリにエンバグ中?
Kobati?
• RDBを利用した永続化フレームワーク
– http://smalltalkhub.com/#!/~kaminami/Kobati
– iBatis、MyBatisっぽい何か
– 命名は駄洒落
• 特徴
– とにかく全てを自分でコントロール
– 設定はXMLファイルに記述
– クエリ結果とオブジェクトのマッピングに注力
やりたかったこと
• やっていることが透けて見える
– 原因と結果の関係が、容易に想像できる
• Smalltalk側はスッキリさせる
– 面倒事は外の世界に任せる
<select id="selectAllEntries" resultMap="selectEntryMap">
SELECT
en.id AS entry_id
, en.title AS entry_title
, en.contents AS entry_contents
, en.updated AS entry_updated
, tag.id AS tag_id
, tag.tag AS tag_tag
, au.id AS author_id
, au.name AS author_name
FROM
Entry AS en
lEFT OUTER JOIN
Entry2Tag AS e2t
ON en.id = e2t.entry_id
LEFT OUTER JOIN
Tag AS tag
ON tag.id = e2t.tag_id
JOIN
Entry2Author as e2a
ON e2a.entry_id = en.id
JOIN
Author as au
ON au.id = e2a.author_id
ORDER BY
en.id
, au.id
, tag.id
</select>
<resultMap id="selectEntryMap" type="KbEntry">
<id property="id" column="entry_id" />
<result property="title" column="entry_title" />
<result property="contents" column="entry_contents" />
<result property="updated" column="entry_updated" />
<association property="author" resultMap="selectAuthorMap" />
<collection property="tags" resultMap="selectTagMap" />
</resultMap>
<resultMap id="selectAuthorMap" type="KbAuthor">
<id property="id" column="author_id" />
<result property="name" column="author_name" />
</resultMap>
<resultMap id="selectTagMap" type="KbTag">
<id property="id" column="tag_id" />
<result property="tag" column="tag_tag" />
</resultMap>
| acc result |
acc := KbDatabaseAccessor for: (KbConfig from: KbExample config).
^ acc transaction:
[:session |
(session getMapper: 'Example-xmlMapper') selectAllEntries].
沿革①
• 2012年春
– Glorpと付き合いたくない
– PragmaにSQLを書けばシンプルでいいのでは?
• VisualWorksでPMapperライブラリ作成開始
selectById: id
<resultType: 'PMapper.PmEntry'>
<selectOne: 'SELECT id, title, contents, updated
FROM PmEntry
WHERE id = :id'>
^self executeQuery
沿革②
• すぐに破綻が見える
– ちょっと大きくなるとシンプルさが消失
selectById: id
<selectOne: ‘
SELECT
id as tag_id,
tag as tag_name
FROM PmTag
WHERE id = :id'>
<resultMap: #(
'PMapper.PmTag'
#(id tag_id)
#(tag tag_name))>
^self executeQuery
沿革③
• 「PragmaにSQLを書く」コンセプトはダメ
– メソッドの中に、複数の、多くの情報を持ったプラ
グマを記述する・・・
– プラグマに構造表現は向いていない
• プラグマやアノテーションで頑張り過ぎるのは良くない
• 構造を取り扱うならXMLがベター
沿革④
• 2012年夏
– Kobati for VisualWorksをひっそりとリリース
• Cincom Public Storeから
沿革④
• 2014年秋
– Pharoに移植
• Pharo対応時に結構手を入れている
• VisualWorks版は追随していない状態
動作環境と使用ライブラリ
• 動作環境
– Pharo3.0
– PostgreSQL
• 使用ライブラリ
– PostgresV3
• http://www.squeaksource.com/PostgresV3.html
• PostgresV3-Core
• PostgresV3-Pool
– XPath
• http://www.smalltalkhub.com/#!/~hernan/XPath
– WideStringPatch
• http://smalltalkhub.com/#!/~kaminami/WideStringPatch
インストール
Gofer it
smalltalkhubUser: 'PharoExtras' project: 'XPath';
configuration;
loadStable.
Gofer it
url: 'http://www.squeaksource.com/PostgresV3';
package: 'PostgresV3-Core';
package: 'PostgresV3-Pool';
load.
Gofer new smalltalkhubUser: 'kaminami'
project: 'Kobati';
package: 'Kobati';
load.
Gofer new smalltalkhubUser: 'kaminami'
project: 'WideStringPatch';
package: 'WideStringPatch';
load.
※
2015年2月27日時点では、これだ
と動かない。
(XPathを用いた設定のパースに
失敗する)
おそらく、XMLParserか、XPathの
バージョンアップでエンバグしてい
る。
WideStringPatch
• マルチバイト文字列の操作が遅い
1. String >> at:put:
2. primitive error
3. WideString >> at:put:
• パッチをあてる
– 100倍程度の速度改善
– Stringでインスタンス生成をする箇所は全てボトルネックとなり得る
String >> convertFromWithConverter: converter
| readStream c |
readStream := self readStream.
^ WideString new: self size streamContents: [ :writeStream|
converter ifNil: [^ self].
[readStream atEnd] whileFalse: [
c := converter nextFromStream: readStream.
c
ifNotNil: [writeStream nextPut: c]
ifNil: [^ writeStream contents]]].
定義するもの
• コンフィグ
– DBとの接続設定、マッパーの指定
• マッパー
– SQL
– SQLとメソッドのマッピング
– クエリ結果とSmalltalkオブジェクトのマッピング
• Smalltalkのクラス定義
Smalltalk側のクラス定義
• 通常のSmalltalkクラスを定義
• 値を設定するためのメソッドを定義
– 必ずしも変数名と合致する必要はない
DB側のイメージ
DBとの接続設定と、マッパーの指定
<configuration>
<environment>
<property name="host" value="localhost"/>
<property name="port" value="5432"/>
<property name="database" value="test"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
<property name="encoding" value="utf8"/>
</environment>
<mappers>
<!--
<mapper resource="ExampleXmlMapper.xml"/>
-->
<mapper eval="KbExample xmlMapper"/>
</mappers>
</configuration>
マッパー
• 記述するもの
– SQL
– SQLとメソッドのマッピング
– クエリ結果とSmalltalkオブジェクトのマッピング
マッパーで使用する主なエレメント
• insert
– selectKey
• update
• delete
• select
• selectOne
• resultMap
• sql
insert①
<!-- Mapper -->
<insert id="insertTag" arguments="tag">
INSERT
INTO Tag
(
tag
)
VALUES (
#{tag.tag}
)
<selectKey keyProperty="tag.id" order="after">
select currval('tag_id_seq')
</selectKey>
</insert>
<!-- Smalltalk -->
insertTag: aTag
| acc result |
acc := KbDatabaseAccessor for: (KbConfig from: self config).
acc transaction:
[:session |
result := (session getMapper: 'Example-xmlMapper') insertTag: aTag].
^ result
この部分は適宜
キャッシュする
#{}で囲まれた部分は値に展開される
insert②
“idのみでメソッドを省略した場合、idをselector扱いする
引数がある場合は自動で : を補完(1個まで)する”
<insert id="insertTag" arguments="tag">
“Smalltalkから呼び出す際のselectorを指定”
<insert id=" insertTag " selector=" insertTag:" arguments=“tag">
“引数を複数とるような場合”
<insert id="insertEntryToFeed" selector="insertEntry:toFeed:" arguments="entry, feed">
“自動採番した値を取得する場合に使用する”
<selectKey keyProperty="tag.id" order="after">
select currval('tag_id_seq')
</selectKey>
値の展開
• #{}で囲まれた部分は値に展開される
– 最終的には、asKobatiSqlLiteralを送信して得られた値
がBindされる
• 例
– メッセージ送信無し
• #{id}
– メッセージ送信有り
• #{tag.id}
• #{anArray.asInValueList}
• #{someArray@1}
• #{someDictonary@someKey}
update
• 使い方はinsertと同様
<update id="updateEntry" arguments="entry">
UPDATE
Entry
SET
title = #{entry.title}
, contents = #{entry.contents}
, updated = now()
WHERE
id = #{entry.id}
</update>
delete
• 使い方はInsertと同様
<delete id="deleteEntry" arguments="entry">
DELETE FROM Entry WHERE id=#{entry.id};
</delete>
selectOne
• クエリ結果1件分をオブジェクトとして返す
– それ以外は、次に紹介するselectと同様
<selectOne id="selectAuthorById" arguments="id" resultType="KbAuthor">
SELECT
id
, name
FROM
Author
WHERE
id = #{id}
</selectOne>
select①
• クエリ結果をコレクションに詰めて返す
• resultMapと連携させる
– 入れ子構造なオブジェクトにも対応できる
– N+1問題も回避できる
select②
• 使用例
<resultMap id="selectAuthorMap" type="KbAuthor">
<id property="id" column="author_id" />
<result property="name" column="author_name" />
</resultMap>
<select id="selectAllAuthors" resultType="KbAuthor">
<![CDATA[
SELECT
id as author_id
, name as author_name
FROM
Author
]]>
</select>
CDATAで囲むことも可能
この例では必要ないが、<>等の演算子を含
める場合に必要
テーブルをJOINした場合などにも使いまわ
したいので、columnに別名を付けている
select③
<select id="selectAllEntries" resultMap="selectEntryMap">
SELECT
en.id AS entry_id
, en.title AS entry_title
, en.contents AS entry_contents
, en.updated AS entry_updated
, tag.id AS tag_id
, tag.tag AS tag_tag
, au.id AS author_id
, au.name AS author_name
FROM
Entry AS en
lEFT OUTER JOIN
Entry2Tag AS e2t
ON en.id = e2t.entry_id
LEFT OUTER JOIN
Tag AS tag
ON tag.id = e2t.tag_id
JOIN
Entry2Author as e2a
ON e2a.entry_id = en.id
JOIN
Author as au
ON au.id = e2a.author_id
ORDER BY
en.id
, au.id
, tag.id
</select>
resultMap①
• クエリ結果とオブジェクトのマッピング
• associationエレメント、collectionエレメントで
入れ子を表現することができる
<resultMap id="selectEntryMap" type="KbEntry">
<id property="id" column="entry_id" />
<result property="title" column="entry_title" />
<result property="contents" column="entry_contents" />
<result property="updated" column="entry_updated" />
<association property="author" resultMap="selectAuthorMap" />
<collection property="tags" resultMap="selectTagMap" />
</resultMap>
<resultMap id="selectAuthorMap" type="KbAuthor">
<id property="id" column="author_id" />
<result property="name" column="author_name" />
</resultMap>
<resultMap id="selectTagMap" type="KbTag">
<id property="id" column="tag_id" />
<result property="tag" column="tag_tag" />
</resultMap>
resultMap②
• 入れ子をまとめて記述することも可能
<resultMap id="selectEntryMap2" type="KbEntry">
<id property="id" column="entry_id" />
<result property="title" column="entry_title" />
<result property="contents" column="entry_contents" />
<result property="updated" column="entry_updated" />
<association property="author" type="KbAuthor">
<id property="id" column="author_id" />
<result property="name" column="author_name" />
</association>
<collection property="tags" type="Set" ofType="KbTag" >
<id property="id" column="tag_id" />
<result property="tag" column="tag_tag" />
</collection>
</resultMap>
type指定なしの場合は
OrderedCollection
sql
• コード片の再利用に使用
<sql id="selectAllTagsSql">
SELECT
id
, tag
FROM
Tag
</sql>
<select id="selectAllTags" resultType="KbTag">
<include refid="selectAllTagsSql"/>
</select>
<selectOne id="selectTagById" arguments="id" resultType="KbTag">
<include refid="selectAllTagsSql"/>
WHERE
id = #{id}
</selectOne>
| acc result |
acc := KbDatabaseAccessor for: (KbConfig from: KbExample config).
^ acc execute: “実行”
[:session |
(session getMapper: 'Example-xmlMapper') selectAllEntries].
Smalltalk側からの呼び出し
| aAuthor acc result |
aAuthor = KbAuthor new.
acc := KbDatabaseAccessor for: (KbConfig from: KbExample config).
^ acc transaction: “トランザクション”
[:session |
(session getMapper: 'Example-xmlMapper') insertAuthor: aAuthor].
| acc result |
acc := KbDatabaseAccessor for: (KbConfig from: KbExample config).
^ acc transaction:
[:session |
session prepare: ‘任意のSQL文字列’; execute].
オブジェクトの組み立て
• 2段階、その分のオーバーヘッドがかかる
• 組み立て順序
– KbObjectBuilder >> buildObjects
1. クエリ結果(Ordered)
2. DictionaryのCollection
3. resultType指定したオブジェクトに詰め替え
終わりに
• まだ実績はないが、ギリギリ使える、はず
• Glorpに疲れたり、馴染めない人の選択肢と
なれるか?

More Related Content

What's hot

Getting Started with Sublime Text 2
Getting Started with Sublime Text 2Getting Started with Sublime Text 2
Getting Started with Sublime Text 2masaaki komori
 
WordPress のキャッシュ機構
WordPress のキャッシュ機構WordPress のキャッシュ機構
WordPress のキャッシュ機構katanyan
 
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)Hiroaki KOBAYASHI
 
WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法regret raym
 
テンプレートエンジンって何?
テンプレートエンジンって何?テンプレートエンジンって何?
テンプレートエンジンって何?Shoichi Takahashi
 

What's hot (6)

Getting Started with Sublime Text 2
Getting Started with Sublime Text 2Getting Started with Sublime Text 2
Getting Started with Sublime Text 2
 
WordPress のキャッシュ機構
WordPress のキャッシュ機構WordPress のキャッシュ機構
WordPress のキャッシュ機構
 
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
 
Embulk 20150411
Embulk 20150411Embulk 20150411
Embulk 20150411
 
WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法
 
テンプレートエンジンって何?
テンプレートエンジンって何?テンプレートエンジンって何?
テンプレートエンジンって何?
 

Similar to SQLマッピングフレームワーク「Kobati」のはなし

StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践Shu Sugimoto
 
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015Mikiya Okuno
 
企業におけるSpring@日本springユーザー会20090624
企業におけるSpring@日本springユーザー会20090624企業におけるSpring@日本springユーザー会20090624
企業におけるSpring@日本springユーザー会20090624Yusuke Suzuki
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼうyouku
 
More Better Nested Set
More Better Nested SetMore Better Nested Set
More Better Nested Setxibbar
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについてtako pons
 
アプリコンテスト
アプリコンテストアプリコンテスト
アプリコンテストTomonori Yamada
 
Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7Sea Mountain
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!Shinpei Ohtani
 
スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門Hisashi HATAKEYAMA
 
Enumはデキる子 ~ case .Success(let value): ~
 Enumはデキる子 ~ case .Success(let value): ~ Enumはデキる子 ~ case .Success(let value): ~
Enumはデキる子 ~ case .Success(let value): ~Takaaki Tanaka
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_QueryHidekazu Ishikawa
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittrkenjis
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうDevTakas
 
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugSpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugY Watanabe
 

Similar to SQLマッピングフレームワーク「Kobati」のはなし (20)

Inside Movable Type
Inside Movable TypeInside Movable Type
Inside Movable Type
 
StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践
 
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
 
企業におけるSpring@日本springユーザー会20090624
企業におけるSpring@日本springユーザー会20090624企業におけるSpring@日本springユーザー会20090624
企業におけるSpring@日本springユーザー会20090624
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼう
 
More Better Nested Set
More Better Nested SetMore Better Nested Set
More Better Nested Set
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについて
 
アプリコンテスト
アプリコンテストアプリコンテスト
アプリコンテスト
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 
スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門
 
Enumはデキる子 ~ case .Success(let value): ~
 Enumはデキる子 ~ case .Success(let value): ~ Enumはデキる子 ~ case .Success(let value): ~
Enumはデキる子 ~ case .Success(let value): ~
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittr
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おう
 
scala-kaigi1-sbt
scala-kaigi1-sbtscala-kaigi1-sbt
scala-kaigi1-sbt
 
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugSpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
 
qmake入門
qmake入門qmake入門
qmake入門
 

SQLマッピングフレームワーク「Kobati」のはなし