-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
597 lines (424 loc) · 45.9 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>tech.usopla.com</title>
<meta name="author" content="monzou">
<meta name="description" content="少し時間があったので, HoneyAnt という Eclipse Plugin を公開しました。
これは Eclipse 上でインクリメンタルに Ant を実行するというプラグインで, 特定のアノテーションが付いたファイルを編集すると, 自動的に Ant が実行されるという機能を提供します。 …">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link href="/atom.xml" rel="alternate" title="tech.usopla.com" type="application/atom+xml">
<link rel="canonical" href="">
<link href="/favicon.png" rel="shortcut icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="container">
<div class="left-col">
<div class="intrude-less">
<header id="header" class="inner"><div class="profilepic">
<img src="/images/dp.jpg" alt="Profile Picture" style="width: 160px;">
</div>
<h1><a href="/">tech.usopla.com</a></h1>
<p class="subtitle">Do you believe in the magic of make-believe ?</p>
<nav id="main-nav"><ul class="main">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<nav id="sub-nav">
<div class="social">
<a class="twitter" href="http://twitter.com/monzou" title="Twitter">Twitter</a>
<a class="github" href="https://github.com/monzou" title="GitHub">GitHub</a>
<a class="rss" href="/atom.xml" title="RSS">RSS</a>
</div>
</nav>
</header>
</div>
</div>
<div class="mid-col">
<div class="mid-col-container">
<div id="content" class="inner">
<article class="post">
<div class="meta">
<div class="date">
<time datetime="2012-12-26T00:02:00+09:00" pubdate data-updated="true">2012/12/26</time></div>
<div class="tags">
<a class='category' href='/blog/categories/java/'>Java</a>
</div>
</div>
<h1 class="title"><a href="/blog/2012/12/26/honeyant/">HoneyAnt</a></h1>
<div class="entry-content">
<p>少し時間があったので, <a href="https://github.com/monzou/honeyant">HoneyAnt</a> という Eclipse Plugin を公開しました。
これは Eclipse 上でインクリメンタルに <a href="http://ant.apache.org/">Ant</a> を実行するというプラグインで, 特定のアノテーションが付いたファイルを編集すると, 自動的に Ant が実行されるという機能を提供します。</p>
<h2>HoneyAnt の使い方</h2>
<p>HoneyAnt を clone すると <code>honeyant-feature-updatesite</code> というプロジェクトがあるので, これを Eclipse でインストールしてください。再起動すると, Java プロジェクトのプロパティに「HoneyAnt」という項が増えているはずです。サンプルとして <code>honeyant-example</code> というプロジェクトも用意しているので, ひとまずこれをベースに説明します。</p>
<p>honeyant-example のプロパティを見ると, HoneyAnt が有効になっており, [ Builders ] に HoneyAnt Runner というビルダが追加されていることが分かると思います。これがインクリメンタルビルドを実行するビルダです。次に Person.java というファイルを開いてください。ただのバリューオブジェクトですが, <code>@HoneyAnt</code> というアノテーションを付与しています(※アノテーションは自由に指定出来ます)。ではここに <code>String sex</code> というプロパティを追加して保存してみましょう。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Buildfile: xxx\honeyant-example\honeyant.xml
</span><span class='line'>
</span><span class='line'>honeyant:
</span><span class='line'> [echo] HoneyAnt incremental build: com.usopla.honeyant.example.source.Person (xxx\honeyant-example\src\main\java\com\usopla\honeyant\example\source\Person.java)
</span><span class='line'> [dump] dump to xxx\honeyant-example\dest\dump.txt
</span><span class='line'>
</span><span class='line'>refresh:
</span><span class='line'>BUILD SUCCESSFUL
</span><span class='line'>
</span><span class='line'>BUILD SUCCESSFUL
</span><span class='line'>Total time: 0 seconds</span></code></pre></td></tr></table></div></figure>
<p>すると自動的に Ant が実行され, このようなログが表示されます。dump.txt を見てみましょう。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>path=xxx\honeyant-example\src\main\java\com\usopla\honeyant\example\source\Person.java
</span><span class='line'>class : com.usopla.honeyant.example.source.Person
</span><span class='line'>package : com.usopla.honeyant.example.source
</span><span class='line'>fields ->
</span><span class='line'> name (java.lang.String)
</span><span class='line'> age (int)
</span><span class='line'> sex (java.lang.String)</span></code></pre></td></tr></table></div></figure>
<p>このように編集後のクラス定義を元にファイルが自動生成されています。ここで実行しているのは <a href="https://github.com/monzou/honeyant/blob/master/honeyant-example/src/main/java/com/usopla/honeyant/example/task/DumpTask.java"><code>DumpTask</code></a> というサンプルの Ant タスクで, クラス情報をリフレクションして適当に出力しています。</p>
<h2>何故つくったか?</h2>
<p>2 年程前に仕事で新しいパッケージプロダクトを作ることになり, そのときにつくったものです(もちろん同じものではなく, 全体的にリファインして HoneyAnt として公開しています)。当時 <a href="http://www.hibernate.org/">Hibernate</a> を使っていたのですが, 折角 O/R マッパーを使っているのにタイプセーフにクエリが書けないことに不満を感じていました。Hibernate には Criteria API というものが存在し, これを使うとある程度オブジェクト指向的にクエリを書くことが出来るのですが, これは(属性名の文字列指定や型情報の欠落を伴う)ランタイムバインドを行うもので, 安全性・保守性・生産性の面から好ましくありませんでした。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="c1">// Hibernate の Criteria API</span>
</span><span class='line'><span class="c1">// プロパティ名を文字列で指定。引数も Object 型。</span>
</span><span class='line'><span class="n">Criteria</span> <span class="n">criteria</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">createCriteria</span><span class="o">(</span><span class="n">Cat</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</span><span class='line'><span class="n">criteria</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">Restrictions</span><span class="o">.</span><span class="na">like</span><span class="o">(</span><span class="s">"name"</span><span class="o">,</span> <span class="s">"Fritz%"</span><span class="o">));</span>
</span><span class='line'><span class="n">criteria</span><span class="o">.</span><span class="na">add</span><span class="o">(</span>
</span><span class='line'> <span class="n">Restrictions</span><span class="o">.</span><span class="na">or</span><span class="o">(</span>
</span><span class='line'> <span class="n">Restrictions</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"age"</span><span class="o">,</span> <span class="mi">0</span><span class="o">),</span> <span class="c1">// 文字列でもバインド出来てしまう</span>
</span><span class='line'> <span class="n">Restrictions</span><span class="o">.</span><span class="na">isNull</span><span class="o">(</span><span class="s">"age"</span><span class="o">)</span> <span class="c1">// プロパティ名を間違えたらランタイムエラーになる</span>
</span><span class='line'> <span class="o">)</span>
</span><span class='line'><span class="o">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>「どうにかタイプセーフに出来ないものか」と悩んでいた当時, <a href="https://sites.google.com/site/slim3appengine/">Slim3</a> のタイプセーフなクエリに感銘を受けて「コレだ!」と思ったのでした。リフレクションを使うのではなく, 予めエンティティのメタ情報を定義しておき, これを用いてクライテリアを表現すればパフォーマンス面でも型安全性の面でも良いのだと気付いたのでした。また 「折角メタ情報を作るのであれば, エンティティのメタ定義からエンティティ, DDL, hbm, クライテリア用のメタクラスも全て自動生成すれば夢が広がるなぁ」などと思いつき, これを実現する方法を考えてみることにしました。</p>
<p>自動生成の実現にあたって, 最初は Slim3 と同じように <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/apt/index.html">APT (Annotation Processing Tool)</a> を用いた自動生成を行おうとしたのですが, APT は意外と自由度が低くファイルの自動生成にはあまり向いていないなと感じました。当初エンティティのメタ情報を Java もしくは Groovy クラスとして定義し, そのクラス情報をリフレクション経由で取得してファイルを自動生成しようとしていたのですが, APT を使うと修正しているファイルのクラス情報を完全に取得することが出来ません(でした……今は違うのかもしれません)。「特定のファイルを編集したときに, もっと自由に自動生成したいなぁ」と思い, Eclipse の Ant を自動的に実行すれば良いかな、と思いついたのでひとまず Eclipse の Plugin をプロトタイプしてみることにしました。Plugin の作り方なんてさっぱり知らなかったのですが, 本やコードを読みながら 2〜3 日ほどかけて実装してみると, 思いのほか上手くいったので APT は止めて Eclipse Plugin にすることにしました。結果的にできあがったのが HoneyAnt でした。</p>
<h2>実際にどのように使ったか?</h2>
<p>さて, 当時の PJ ではエンティティは全てメタ定義(Java クラス・ランタイムでアプリケーションに含まれない)を元に HoneyAnt で自動生成しました。例えば <a href="http://www.redmine.org/">Redmine</a> のようなプロジェクト管理アプリケーションの「プロジェクト」をサンプルにすると, メタ定義はこんな感じです(適当な例にしています)。テーブル名やカラム名をデフォルトで推測したり, Hibernate の主要な機能は一通り使えるようにしたりしました。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="nd">@HoneyAnt</span><span class="o">(</span><span class="s">"ユーザー"</span><span class="o">)</span>
</span><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserSource</span> <span class="kd">extends</span> <span class="n">ClassSource</span> <span class="o">{</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"ID"</span><span class="o">)</span>
</span><span class='line'> <span class="n">NumberProperty</span><span class="o"><</span><span class="n">Long</span><span class="o">></span> <span class="n">id</span> <span class="o">=</span> <span class="n">sequenceIdProperty</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"名前"</span><span class="o">)</span>
</span><span class='line'> <span class="n">StringProperty</span> <span class="n">name</span> <span class="o">=</span> <span class="n">stringProperty</span><span class="o">(</span><span class="mi">20</span><span class="o">).</span><span class="na">notNull</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"メールアドレス"</span><span class="o">)</span>
</span><span class='line'> <span class="n">StringProperty</span> <span class="n">email</span> <span class="o">=</span> <span class="n">stringProperty</span><span class="o">(</span><span class="mi">50</span><span class="o">).</span><span class="na">notNull</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"管理者"</span><span class="o">)</span>
</span><span class='line'> <span class="n">BooleanProperty</span> <span class="n">admin</span> <span class="o">=</span> <span class="n">primitiveBooleanProperty</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"ステータス"</span><span class="o">)</span>
</span><span class='line'> <span class="n">UserTypeProperty</span><span class="o"><</span><span class="n">UserStatus</span><span class="o">></span> <span class="n">status</span> <span class="o">=</span> <span class="n">userTypeProperty</span><span class="o">(</span><span class="n">UserStatus</span><span class="o">.</span><span class="na">class</span><span class="o">).</span><span class="na">notNull</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="nd">@HoneyAnt</span><span class="o">(</span><span class="s">"プロジェクト"</span><span class="o">)</span>
</span><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ProjectSource</span> <span class="kd">extends</span> <span class="n">ClassSource</span> <span class="o">{</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"ID"</span><span class="o">)</span>
</span><span class='line'> <span class="n">NumberProperty</span><span class="o"><</span><span class="n">Long</span><span class="o">></span> <span class="n">id</span> <span class="o">=</span> <span class="n">sequenceIdProperty</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"序数"</span><span class="o">)</span>
</span><span class='line'> <span class="n">NumberProperty</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span> <span class="n">sequenceNo</span> <span class="o">=</span> <span class="n">primitiveIntProperty</span><span class="o">(</span><span class="mi">10</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"名称"</span><span class="o">)</span>
</span><span class='line'> <span class="n">StringProperty</span> <span class="n">name</span> <span class="o">=</span> <span class="n">stringProperty</span><span class="o">(</span><span class="mi">50</span><span class="o">).</span><span class="na">notNull</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"ステータス"</span><span class="o">)</span>
</span><span class='line'> <span class="n">UserTypeProperty</span><span class="o"><</span><span class="n">ProjectStatus</span><span class="o">></span> <span class="n">status</span> <span class="o">=</span> <span class="n">userTypeProperty</span><span class="o">(</span><span class="n">ProjectStatus</span><span class="o">.</span><span class="na">class</span><span class="o">).</span><span class="na">notNull</span><span class="o">();</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Property</span><span class="o">(</span><span class="s">"メンバー"</span><span class="o">)</span>
</span><span class='line'> <span class="nd">@Index</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"IXA_PROJECT_01"</span><span class="o">)</span>
</span><span class='line'> <span class="n">ManyToManyProperty</span><span class="o"><</span><span class="n">User</span><span class="o">>></span> <span class="n">users</span> <span class="o">=</span> <span class="n">manyToMany</span><span class="o">(</span><span class="n">UserSource</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="s">"PROJECT_USER_RELATION"</span><span class="o">).</span><span class="na">lazy</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>このファイルからおおよそ以下が HoneyAnt により自動生成されます。</p>
<ol>
<li>エンティティ・エンティティの基底クラス(Generation Gap パターン)</li>
<li>エンティティメタクラス・エンティティメタ基底クラス(Generation Gap パターン)</li>
<li>hbm</li>
<li>DDL</li>
<li>テーブル定義書等</li>
</ol>
<p>これだけでも十分便利なのですが, このときに一番実現したかったものは「タイプセーフなクエリ」です。これを実現する際の肝になっているのが 2. の「エンティティメタクラス」です。このメタクラスを使用してタイプセーフクライテリアを実現しました。タイプセーフクライテリアの実現に当たっては, まずタイプセーフなクライテリア API を作り, 次に HoneyAnt でこの API を利用したエンティティメタクラスを自動生成するようにしました。エンティティメタクラスを利用したタイプセーフなクライテリアは, 以下の場面で使用しました。</p>
<ul>
<li>DAO(Hibernate の Criteria API に変換してタイプセーフなクエリを実現)</li>
<li>継続クエリ(OQL に変換してサーバサイドに登録し, メッセージフィルタとして使用)</li>
</ul>
<p>クライテリア API を独立させることによって, 様々な場面で活用出来る拡張性を持たせています。パーサさえ書けば様々な要素にバインド出来るので, <a href="http://www.mongodb.org/">MongoDB</a> 用のアダプタなんかも作ろうかなと思っていました(このときは使用しなかったので作りませんでしたが)。</p>
<p>では実際に使う場合の簡単な例を紹介します。DAO として使用する場合はこんな感じです(クエリの意味は適当ですスミマセン)。ここではひとつずつ検索条件をその場で作っていますが、<a href="http://rubyonrails.org/">Rails</a> の Named Scope のようにメタクラスに条件を定義することも出来ます。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">ProjectMeta</span> <span class="n">meta</span> <span class="o">=</span> <span class="n">ProjectMeta</span><span class="o">.</span><span class="na">getInstance</span><span class="o">();</span>
</span><span class='line'><span class="n">Dao</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">dao</span> <span class="o">=</span> <span class="n">daoFactory</span><span class="o">.</span><span class="na">createDao</span><span class="o">(</span><span class="n">meta</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// ex. update</span>
</span><span class='line'><span class="n">dao</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">project</span><span class="o">);</span>
</span><span class='line'><span class="n">dao</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">project</span><span class="o">);</span>
</span><span class='line'><span class="n">dao</span><span class="o">.</span><span class="na">delete</span><span class="o">(</span><span class="n">project</span><span class="o">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// ex. entity-query(エンティティ単位)</span>
</span><span class='line'><span class="o">{</span>
</span><span class='line'> <span class="n">EntityQuery</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">query</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">createQuery</span><span class="o">();</span>
</span><span class='line'> <span class="n">query</span><span class="o">.</span><span class="na">orderBy</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">id</span><span class="o">,</span> <span class="n">Order</span><span class="o">.</span><span class="na">ASC</span><span class="o">);</span>
</span><span class='line'> <span class="n">Criteria</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">criteria</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="na">createCriteria</span><span class="o">().</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">sequenceNo</span><span class="o">.</span><span class="na">lt</span><span class="o">(</span><span class="mi">5</span><span class="o">)).</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">status</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="n">ProjectStatus</span><span class="o">.</span><span class="na">ACTIVE</span><span class="o">));</span>
</span><span class='line'> <span class="n">List</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">projects</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="na">list</span><span class="o">(</span><span class="n">criteria</span><span class="o">);</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// ex. projection-query(射影)</span>
</span><span class='line'><span class="o">{</span>
</span><span class='line'> <span class="n">ProjectionQuery</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">query</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">createProjectionQuery</span><span class="o">();</span>
</span><span class='line'> <span class="n">Criteria</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">criteria</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="na">createCriteria</span><span class="o">().</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">admin</span><span class="o">.</span><span class="na">isTrue</span><span class="o">()).</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">status</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="n">UserStatus</span><span class="o">.</span><span class="na">ACTIVE</span><span class="o">));</span>
</span><span class='line'> <span class="n">List</span><span class="o"><</span><span class="n">Long</span><span class="o">></span> <span class="n">userIds</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="na">listValues</span><span class="o">(</span><span class="n">criteria</span><span class="o">,</span> <span class="n">meta</span><span class="o">.</span><span class="na">id</span><span class="o">);</span> <span class="c1">// もちろん複数プロパティの射影も可能</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// ex. aggregation-query(集約)</span>
</span><span class='line'><span class="o">{</span>
</span><span class='line'> <span class="n">AggregationQuery</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">query</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">createAggregationQuery</span><span class="o">();</span>
</span><span class='line'> <span class="n">AggregationFunctionProperty</span><span class="o"><</span><span class="n">Project</span><span class="o">,</span> <span class="n">Long</span><span class="o">></span> <span class="n">maxUserIdProperty</span> <span class="o">=</span> <span class="n">Aggregations</span><span class="o">.</span><span class="na">max</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">id</span><span class="o">);</span>
</span><span class='line'> <span class="n">Criteria</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">criteria</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="na">createCriteria</span><span class="o">().</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="mi">1L</span><span class="o">)).</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">status</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="n">UserStatus</span><span class="o">.</span><span class="na">ACTIVE</span><span class="o">));</span>
</span><span class='line'> <span class="n">Long</span> <span class="n">maxUserId</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="na">uniqueValue</span><span class="o">(</span><span class="n">criteria</span><span class="o">,</span> <span class="n">maxUserIdProperty</span><span class="o">);</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>見ての通り一通りタイプセーフにクエリが出来るようになっています。当然ですがクライテリアには強い型制約を持たせています。上記の例ではプロパティ同士の比較はしていませんが, 例えばプロパティ同士の比較クライテリオン ge (greater than or equals to) はこんな感じのシグネチャです。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="c1">// E はエンティティの型・C は比較される値の型</span>
</span><span class='line'><span class="o"><</span><span class="n">E</span><span class="o">,</span> <span class="n">C</span> <span class="kd">extends</span> <span class="n">Comparable</span><span class="o"><?</span> <span class="kd">super</span> <span class="n">C</span><span class="o">>></span> <span class="n">PropertyCompareCriterion</span><span class="o"><</span><span class="n">E</span><span class="o">,</span> <span class="n">C</span><span class="o">,</span> <span class="n">ComparableProperty</span><span class="o"><?</span> <span class="kd">super</span> <span class="n">E</span><span class="o">,</span> <span class="n">C</span><span class="o">>></span> <span class="n">ge</span><span class="o">(</span><span class="n">ComparableProperty</span><span class="o"><?</span> <span class="kd">super</span> <span class="n">E</span><span class="o">,</span> <span class="n">C</span><span class="o">></span> <span class="n">condition</span><span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>かなり強い型制約を持たせていることが分かるかと思います。</p>
<p>継続クエリとして使用するときも同じクライテリア API を用いることが出来ます。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">ProjectMeta</span> <span class="n">meta</span> <span class="o">=</span> <span class="n">ProjectMeta</span><span class="o">.</span><span class="na">getInstance</span><span class="o">();</span>
</span><span class='line'><span class="n">Criteria</span><span class="o"><</span><span class="n">Project</span><span class="o">></span> <span class="n">criteria</span> <span class="o">=</span> <span class="n">meta</span><span class="o">.</span><span class="na">createCriteria</span><span class="o">().</span><span class="na">add</span><span class="o">(</span><span class="n">meta</span><span class="o">.</span><span class="na">status</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="n">ProjectStatus</span><span class="o">.</span><span class="na">ACTIVE</span><span class="o">));</span>
</span><span class='line'><span class="n">CriteriaFilter</span> <span class="n">filter</span> <span class="o">=</span> <span class="n">CriteriaFilterFactory</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">criteria</span><span class="o">);</span>
</span><span class='line'><span class="kt">boolean</span> <span class="n">b</span> <span class="o">=</span> <span class="n">filter</span><span class="o">.</span><span class="na">apply</span><span class="o">(</span><span class="n">project</span><span class="o">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>同じ API を使用しているので, 検索条件をひとつ作れば DB アクセスにも継続フィルタを使用した非同期更新キャッシュなんかにも使うことが出来ます。</p>
<h2>というわけで</h2>
<p>色々な用途に使えると思うので, 良ければご自由にお使い下さい。</p>
<p>Java で DSL を作るのは難しいです。DSL を定義するのであれば Groovy や Ruby を使った方がよほど楽でしょう。ですので Java で DSL を無理矢理つくるよりは、タイプセーフなメタ情報を自動生成するのが個人的にはオススメです。今なら <a href="http://www.eclipse.org/Xtext/">Xtext</a> を使うのもひとつ有効な手段なのかもしれませんが、使い慣れた Java で Ant タスクとして自動生成処理を定義したい場合には HoneyAnt を使うのも良いかなと思います。</p>
</div>
</article>
<article class="post">
<div class="meta">
<div class="date">
<time datetime="2012-12-22T14:28:00+09:00" pubdate data-updated="true">2012/12/22</time></div>
<div class="tags">
<a class='category' href='/blog/categories/git/'>git</a>
</div>
</div>
<h1 class="title"><a href="/blog/2012/12/22/subversion-to-git/">Subversion to Git</a></h1>
<div class="entry-content">
<div style="width: 650px">
<script async class="speakerdeck-embed" data-id="d8d803202e250130a32512313918315a" data-ratio="1.6" src="//speakerdeck.com/assets/embed.js"></script>
</div>
<p>勤務先は未だに Subversion を使っているのですが、いい加減 git を使いましょうということで先日勉強会を開催したのでそのときに使用した資料を Speaker Deck にアップロードしてみました。一部社外に公開出来ないところは削除したり改変したりしているため少々おかしいところがありますが、殆ど社内勉強会で使用した資料と同じものです。良ければご参照ください。勤務先では基本的に Windows + Eclipse 環境で開発している人が多いので、Eclipse や GitHub for Windows によるデモを交えた勉強会にしました。そのため、資料中でも <a href="http://www.eclipse.org/egit/">EGit</a> や <a href="http://windows.github.com/">GitHub for Windows</a> に関する記述が出てきます。ちなみに EGit は今回初めて評価してみたのですが、思った以上に良く出来ていて業務での利用には全く問題ないと判断しました。勿論 git の様々な操作を全て使用出来るようにはなっていませんが、一般的なコマンドについてはカバーしていますし、難しい操作については GitHub for Windows に付属する Shell を使えば問題ありません。</p>
<h2>Subversion の嫌なところ</h2>
<p>Subversion を使っていて日常的に困るのは以下のようなケースです。</p>
<ol>
<li>「とりあえずコミット」が横行するのできちんとしたコードレビューが難しい(レビュー対象が散乱する)</li>
<li>手元の作業記録を簡単に記録出来ないので気楽にリファクタリングすることが出来ない(大規模なリファクタリング中にあれこれ試すのが難しい)</li>
<li>(同じ理由により)並行作業がしづらい(手元でコードを書いているときに別作業を頼まれたら苦労する)</li>
</ol>
<p>git にはローカルリポジトリがあるのでこのような問題点が解決出来ます。</p>
<ol>
<li>コミットを整理してから push 出来る</li>
<li>手元で色々なブランチを作って作業出来る</li>
<li>作業途中で stash 出来る</li>
</ol>
<p>素敵ですよね。</p>
<h2>git が生み出すもの</h2>
<p>勉強会では git を採用することのメリットについてあれこれ話しました。「git を導入したらどれぐらい生産性が上がるの?」というのは、PC やモニタを買うのと一緒でなかなか数値化することが難しいものではありますが、少なくとも参加した皆さんにはある程度良い感触を持ってもらえた思えてもらえたんじゃないかな……?と思います。
個人的には</p>
<ol>
<li>バリバリ開発している人(コア開発者)ほど生産性が上がる</li>
<li>(コア開発者は大抵コードレビューも行うので)コードレビューの時間が取れるようになる</li>
<li>コードレビューの時間が取れる + git 効果でレビューしやすくなるのでレビューの質が上がる</li>
<li>細かなコードレビューでジュニアなメンバーのスキルアップにもつながる</li>
<li>ますますコア開発者の生産性が上がる</li>
</ol>
<p>という良いサイクルを生み出すことが出来るんじゃないかと思っています。また、GitHub や Stash を導入することでエンジニア同士の交流が活性化して、会社の雰囲気や文化が少しでも変わっていく端緒となれば良いなと期待しています。</p>
<h2>気付いたこと</h2>
<p>今まで勉強会など参加したことも殆ど無かったですし、ましてや自分が主催したり発表したりすることも勿論無かったので、今回が初めての経験でした。いざ自分でやってみると、勉強会に参加する態度によって学習効果が大きく違うんだなということを再確認しました。</p>
<ul>
<li>受動的に参加する(相手が言っていることを鵜呑みにするだけ)</li>
<li>能動的に参加する(相手が言っていることを理解しようと努める・疑問を持つ・質問する)</li>
<li>自分でプレゼンする</li>
</ul>
<p>下にいくほど学習効果が高いわけです。良く言われていることですが、今回改めてそのことを実感しました。勉強会でプレゼンしようと思うと事前にしっかり準備しないといけません。資料をつくったり、理解が曖昧なところを深堀しないといけません。</p>
<p>何かを学ぶとき、(相当頭の良い人は別だけど)ふつうの人は受動的に情報を仕入れているだけでは想像力が働きません。けれど人に説明するためにしっかり理解しようとすると、その過程で様々な疑問が出てくる。「調べてみるとこんなことが言われているけど、いったいどういうことなんだろう?」「これはもしかしてこういうことなんじゃないか?」などと<strong>自分の想像力を働かせる機会が増え、曖昧だった知識が体系化され、自分の中の血肉として育っていく</strong>。だから勉強会をするのは(例え自分が理解している「つもり」の物事をテーマにしたとしても)意味のある行為だな、今後はもっと自分で勉強会を主催しよう、などと思ったのでした。</p>
</div>
</article>
<article class="post">
<div class="meta">
<div class="date">
<time datetime="2012-12-14T01:14:00+09:00" pubdate data-updated="true">2012/12/14</time></div>
<div class="tags">
<a class='category' href='/blog/categories/misc/'>Misc</a>
</div>
</div>
<h1 class="title"><a href="/blog/2012/12/14/hello-octopress/">Hello Octopress</a></h1>
<div class="entry-content">
<p>前々から日記以外に技術系のブログをひとつ作りたかったので Octopress + GitHub Pages で構築してみました。人に見られることを想定したブログというものはここ数年作っていなかったので本当に久しぶり。主に技術ネタを扱っていきたいと思っているので横幅を広く取れるテーマにしてみました。以下備忘録。</p>
<h2>ブログの設定を変更したとき</h2>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ git add .
</span><span class='line'>$ git commit -m 'message'
</span><span class='line'>$ git push origin source</span></code></pre></td></tr></table></div></figure>
<h2>記事を書くとき</h2>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ bundle exec rake new_post["title_in_english"]
</span><span class='line'>$ vim source/_posts/your_new_post.markdown
</span><span class='line'>$ bundle exec rake generate
</span><span class='line'>$ bundle exec rake preview -- http://localhost:4000
</span><span class='line'>$ bundle exec rake gen_deploy</span></code></pre></td></tr></table></div></figure>
</div>
</article>
<nav id="pagenavi">
<div class="center"><a href="/blog/archives">Blog Archives</a></div>
</nav></div>
</div>
<footer id="footer" class="inner">Copyright © 2012
monzou
Design credit: <a href="http://shashankmehta.in/archive/2012/greyshade.html">Shashank Mehta</a></footer>
<script src="/javascripts/slash.js"></script>
<script src="/javascripts/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
(function($){
$('.fancybox').fancybox();
})(jQuery);
</script> <!-- Delete or comment this line to disable Fancybox -->
<script type="text/javascript">
var disqus_shortname = 'tech-usopla';
var disqus_script = 'count.js';
(function () {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://' + disqus_shortname + '.disqus.com/' + disqus_script;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-37126998-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</div>
</div>
</body>
</html>