2015年4月15日水曜日

はてなブログ(http://ohbarye.hatenablog.jp/)に引っ越した

最近はもっぱらMarkdownを書くようになり、Bloggerがどんどん使いづらくなってきたのではてなブログに引っ越した。
http://ohbarye.hatenablog.jp/

下記リンク先が大変参考になり、10分ほどで作業を終えることができた。
http://nekonkeo.hatenablog.com/entry/2014/09/23/165817

2015年3月13日金曜日

グラフDB(Neo4j)を試してみる (2)BluePrintsで読み書き

BluePrints

各グラフDBに対するインタフェース、APIを提供するソフトウェア。
複数のグラフDBに対応している。

ライブラリ追加

blueprints-core と好きなGraphDB用のライブラリを追加する。
今回はNeo4jを選んだので blueprints-neo4j-graph を追加。
手元でちょうどPlay Framework触ってたのでビルドツールはSBT。
libraryDependencies ++= Seq(
  "com.tinkerpop.blueprints" % "blueprints-core" % "2.6.0",
  "com.tinkerpop.blueprints" % "blueprints-neo4j-graph" % "2.6.0"
)

DB初期化〜読み書き

DBの初期化からデータの追加、検索を行うとこんな感じになる。
package app;
 
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.neo4j.Neo4jGraph;
 
public class GraphDB {
 
 public static void main(String[] args) {

  /**
   * init
   * 使用するグラフDB用のディレクトリを指定する。
   * このタイミングでロックファイルを作成し、排他制御をかける。
   * ディレクトリが存在しない場合は初期化してくれる。
   */
  Graph g = new Neo4jGraph("data/graphdb");
  
  addData(g);
  showData(g);

  /**
   * close
   * プログラムを終了する時は必ずshutdown。
   * ロックの解放とか諸々やってるっぽい。
   */
  g.shutdown();
 }
 
 /**
  * Add Node and Edge
  * @param g
  */
 public static void addData(Graph g) {
  /**
   * insert
   * Vertex(頂点、Node)の追加+属性の追加。
   */
  Vertex v1 = g.addVertex(1);
  v1.setProperty("name", "Apache");
  
  Vertex v2 = g.addVertex(2);  
  v2.setProperty("name", "Nginx");
  
  /**
   * insert
   * Edge(辺、Link)の追加+属性の追加。
   */
  Edge e1 = g.addEdge(1, v1, v2, "similar");
  e1.setProperty("since", 2006);
 }
 
 /**
  * show graph data
  * @param g
  */
 public static void showData(Graph g) {
  /**
   * select
   * とりあえず全部取得して表示。
   */
  for (Vertex v : g.getVertices()) {
   System.out.println("Vertex id = " + v.getId().toString()
     + "  property 'name' = " + v.getProperty("name"));
  }
 
  for (Edge e : g.getEdges()) {
   System.out.println("Edge id = " + e.getId().toString()
     + "  property 'since' = " + e.getProperty("since"));
  }
 }
}
Vertex id = 1 property 'name' = Apache Vertex id = 2 property 'name' = Nginx Edge id = 0 property 'since' = 2006

初見の印象

とりあえず触ってみたところ、特に良いなと思ったのが下記。
  • サーバ構築不要
  • 移植性が高い
BruePrintsにはNeo4jのライブラリが同梱されているらしく、DBとはいうもののサーバ構築やサービス起動などの一般的なミドルウェア追加時の作業を行わなくても上記のコードだけで扱うことができる。

もちろん、サーバとして起動して外部からのアクセスを待ち受けたりもできるとのこと。

また、移植性も高い。
new Neo4jGraph(“data/graphdb”) で指定したディレクトリの移動だけで移植が完了する模様。

グラフDBにはスケールしづらいという弱点があるらしいが、その分これだけ軽量になっているのは魅力的。





2015年3月12日木曜日

グラフDB(Neo4j)を試してみる (1)グラフDBとは

会社の勉強会でグラフDBが紹介されて興味を持ったので実践してみた。
全然知らない領域だったのでいろいろ整理したい。

グラフDBとは

まずグラフDBとは何か。

グラフ理論をベースとし、ノード(頂点)とエッジ(関係)を構成要素とするNoSQLデータベースの一つ。関係性を表現が目的のため、その探索が用意。また、ノード・エッジはプロパティ(属性)を持つことができる。

とりあえずこんな理解。

一般的な「グラフ」とは意味合いが違うけれども、計算機科学や数学では「グラフ」といえばこちらを指すことが多いのだろうか。ちなみにWikipediaのグラフ理論がだいぶ参考になった。
グラフ理論(グラフりろん、graph theory)は、数学の一分野。ノード節点頂点[1])の集合とエッジ[2])の集合で構成されるグラフの性質について研究する学問である。なお「エッジ」をリンク[3]という場合もある。コンピュータのデータ構造アルゴリズムなどに広く応用されている。  
Wikipedia グラフ理論
このグラフ構造はRDBでも実現できるが、リレーションを辿る=結合の繰り返しになるのでクエリが複雑になったりパフォーマンスがひどいものになったりする。FacebookやTwitterに代表されるようなリレーションをコアとするアプリケーションでのデータ管理や表現への注目の高まり、

Neo4j

試してみたグラフDBはNeo4j。この他にもいろいろあるらしいけど未知。
グラフデータベース、NOSQL、Neo4jを見ると非OSSが多い印象。

TinkerPop

グラフDBを利用する為のフレームワーク、製品群。
ややキモいキャラクターが各プロダクトのトレードマークっぽい。
TinkerPop - http://goo.gl/zpCCC

今回はこのうちBluePrintsとGremlinを使ってグラフDBへアクセス、読み書きを行ってみた。

長くなりそうなのでコードは次の記事で書く。




2015年3月1日日曜日

[Play Framework] 多対多で自己再帰の関連を持つテーブルのEntity

多対多(Many To Many)で自己再帰的(self recursive)な関係をEbean の Model で表現するのに苦戦した。
あまり良い例ではないけど、
person には似てる人(similarPerson)が複数いる、という設定で書いてみた。
person と person の多対多を解消する中間テーブルは similar_person として定義してみる。
@Entity
public class Person {
    @Id
    public Long id;

    @ManyToMany
    @JoinTable(name = "similar_person",
            joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "similar_person_id", referencedColumnName = "id"))
    public List similarPersons;
}
ポイントは @JoinTable の引数の joinColumns と inverseJoinColumns 。
最初これらを書かずにいたら、similar_person テーブルで列名 person_id が重複しています と怒られた。

考えてみたらどちらも外部参照先 (person.id) は同じなんだから、列名指定せずに自動生成したらそうなるよな…。

上記のクラスを定義した上で Evolution を実行すると、下記SQL が自動生成される。
# --- Created by Ebean DDL
# To stop Ebean DDL generation, remove this comment and start using Evolutions

# --- !Ups

create table similar_person (
  person_id                     bigint not null,
  similar_person_id             bigint not null,
  constraint pk_similar_person primary key (person_id, similar_person_id))
;

alter table similar_person add constraint fk_similar_person_person_01 foreign key (person_id) references person (id) on delete restrict on update restrict;

alter table similar_person add constraint fk_similar_person_person_02 foreign key (similar_person_id) references person (id) on delete restrict on update restrict;

# --- !Downs

SET REFERENTIAL_INTEGRITY FALSE;

drop table if exists similar_person;

JPA をちゃんと理解してなかったのでけっこうハマった。

【参考】

JPA – Recursive ManyToMany-Relationship | stuetzpunkt -


[Play Framework] Play2.2.x で Java8 の記法で書いたらコンパイルエラーになった

Play2.2.x で play new したプロジェクトを素のまま使っていて Java8 の記法で書いたらコンパイルエラーになった。
2.2系は Java8 対応してないとのこと。

SBT のバージョン上げたら動くようにはなったけど、問題がありそうなので正式対応した 2.3系を使おう。

【参考】

[play-framework] Error Unknown constant: 18 - Grokbase - 


2015年2月4日水曜日

[Java][Excel][JETT] Excel帳票出力にJETTを試してみる

シフト表作成アプリ作る中で、Excel帳票を出力したくなったので軽くライブラリについて調べて見る。

調べる前に、以前に使ったことあるやつ

POI …以前に実務で帳票ガリガリ書いてたけど、かなりプリミティブで結構辛かった。なので生で使うのは本当に必要な時だけにしたい。
Fisshplate …テンプレートを使ってみて、やっぱりコレぐらいサクサク書けない と困ると実感した。ただ、今回出力したい xlsx 形式に対応していない(対応予定なし?)のでスルー。

Java × Excel だと POI の話題ばかり

Java8 / play framework でやっており、とりあえず最近だとどんなライブラリがあるのかと思い調べてみると、POI の話題ばかり。

どのライブラリも POI ベースでそれをラップするのが基本ぽいのに、もしかして皆 POI で頑張ってるのか…??

そんな中 Excel方眼紙を支える技術 - 新・たけぞう瀕死の日記 がかなり参考になった。

JETT を試して見る

なんとなく先端ぽく、↓の比較も面白かったので今回は帳票出力用ライブラリ JETT を試してみることにした。
本家サイトの jXLS との比較:JETT - Comparison to jXLS

とりあえずテンプレートファイルへの出力を試す。

1.テンプレートファイルを用意する。
2.出力コードを書く。

 public static File makeShift() {
  System.out.println(System.getProperty("user.dir"));
  
  List<employee> employees = Lists.newArrayList();
  
  Map<string object=""> beans = Maps.newHashMap();
  Employee emp = new Employee();
  emp.name = "Butcher";
  emp.skillLevel = "High";
  
  employees.add(emp);
  
  beans.put("employees", employees);
  
  String inPath  = "resources/shift_template.xlsx";
  String outPath = "resources/shift.xlsx";
  
  try (FileOutputStream fileOut = new FileOutputStream(outPath);
    InputStream fileIn       = new BufferedInputStream(new FileInputStream(inPath))) {

   ExcelTransformer transformer = new ExcelTransformer();
   Workbook workbook = transformer.transform(fileIn, beans);
   workbook.write(fileOut);
   fileOut.close();
   
  } catch (IOException e) {
   System.err.println("IOException reading " + inPath + ": " + e.getMessage());
  } catch (InvalidFormatException e) {
   System.err.println("InvalidFormatException reading " + inPath + ": " + e.getMessage());
  }
  
  return new File(outPath);  
 }

余分なコードが多いが、テンプレートへの出力処理は ExcelTransformer#transform で JavaBeans を渡すだけでOKなのでかなり簡潔。

テンプレートファイルに記述する構文もシンプルで良い。
個人的に、forEach タグを利用する時にデータの無い行や列にタグを書かなくて良いのは嬉しい。

番外

その他、調べて評判良かったのが ExCella だったけど、Maven repository に登録されておらずライブラリ管理を考えるのが面倒になってスルーした。
(今回は play なので build.sbt で管理)