Web www.physalis.net

2008
< 7
MonTueWedThuFriSatSun
123456
78910111213
14151617181920
21222324252627
28293031

Recent Pages:

Recent Comments:

Recent Trackbacks:

4/8/08
ひさびさに Wicket さわった
祭に参加するためにさわったとか、ないわー
Author:akira 1:20:58 AM Comments (1) Trackbacks (0) Tags:
1/27/08
Twitter で特定のメッセージを投稿できない
Twitter を使っていて、特定のメッセージを投稿できなかった経験はありませんか? これまで NG ワードかと思っていたのですが、僕が遭遇した問題に関して言えばコマンドの解釈のされ方によるもののようです。


どんなメッセージを投稿できないの?

たとえば次のものは発言できません。

  • こんにちはw
  • ヾ(・ω・*)ノ
顔文字の方は @yuyarin さんのブログで知りました (http://d.hatena.ne.jp/yuyarin/20071112/1194835796)。他にもありますが日本語ユーザがハマりやすいのは上記じゃないでしょうか。


投稿できないときはどうなるの?

web や IM から投稿するとエラーメッセージが表示されます。こんな感じ。

  • Mysteriously Unnamed, since Aug 2006.
  • You have made 's latest update a favorite.
これじゃなんのことはわからないですよね。

困ったことに API から実行するとエラーになりません。(※1)

※1 空の応答が返るときと、投稿に成功した最後のメッセージの ID が返ってくることがあります。後者を使えば判別できますが前者は正常な場合にも返されるので判別できません。


じゃあ原因は?

結論から言うと Twitter のコマンドが影響しているようです。Twitter ではメッセージを入力するところに書けるコマンドがいくつか用意されています。本家のヘルプはこちらです。(http://twitter.com/help/lingo)

ここにあるのが全てではなく他にもあります。どうやら半角の w や * (アスタリスク) もコマンドのようなのです。

w は whois コマンド (本家ヘルプには書いてありませんが) の短縮系で

w akr
のように使います。web と IM ではこんなふうに表示されます。
akr, since Apr 2007. bio: 犬好きの Java 好きのピンボール好きです。

ややこしいのは Twitter はコマンドが文頭になくても、英数字 (と一部の記号 ※2) 以外を無視してコマンドと認識してしまうのです。たとえば上の例の "こんにちはw" は w コマンドと解釈されます。web から "こんにちはw akr" とやってみてください。

※2 調べた範囲では ! が該当します。

上の例の顔文字の方はというと、* (アスタリスク) がコマンドです。

* akr
とすると @akr の最後の発言を favorite に入れます。
  • ヾ(・ω・*)ノ
の場合 * の前にあるのは英数字 (と一部の記号) 以外の文字なので * コマンドと解釈されてしまいます。


どうすれば投稿できるの?

コマンドに解釈されなければ投稿できます。方法はふたつあります。

  • w や * の前に英数字か記号を書く
"aこんにちはw" なら投稿できます。! を使って "!こんにちはw" とした方が見やすいかもしれません。
  • コマンド文字を複数個入れる
コマンドに解釈される文字 w、* や d などを複数回入れれば回避できます。 "wこんにちはw" や "*こんにちはw" は投稿できます。(笑) の意味の w であれば "こんにちはww" のように 2 個以上使えば大丈夫です。


まとめ

投稿できない問題は、コマンドと解釈されてしまうのが原因のようです。特に w は <日本語>w の形式になることが多く投稿できないパターンにハマりやすいです。

困るのが API クライアントです。上に書いたように API ではエラーを完全に知ることができません。最近 API クライアントで投稿できないという話をちょくちょく聞きますが、ほとんど (全て?) がこの問題に該当しているのではないかと思っています。

クライアント側での対応が必要かもしれませんね。
API にコマンドを解釈しないオプションを要望しています。(http://getsatisfaction.com/twitter/topics/request_for_ignore_commands_feature_for_api_statuses_update) ぜひ "I like this idea!" をクリックしてください。(下の方にある黄色のボタンです)

Author:akira 11:09:22 PM Comments (0) Trackbacks (0) Tags: twitter
12/25/07
夏ライオン
Twitter クライアント 「夏ライオン」についてはこちら (http://www.physalis.net/ss/space/NatsuLion) をどうぞ。
Author:akira 2:51:10 AM Comments (0) Trackbacks (1) Tags: cocoa twitter
10/28/07
SnipSnap その後
このブログは以前は SnipSnap (http://snipsnap.org) で動かしていたのですが、今は SnipSnap のコンセプトを参考にして Wicket + Spring + Hibernate で作った自作のシステムで動かしています。

Wicket でシステムを作りたかったのもありますが、SnipSnap の更新が遅かったのが大きな理由です。

そんな SnipSnap も今年の 6 月に開発終了がアナウンスされ、有志で開発を継続する体制が整いつつあるところです。

これまでの経緯をまとめてみたいと思います。

  • SnipSnap は Leo と Stephan の二人がコミッタとして開発を続けていました
  • 彼等以外がパッチを送って反映する体制になっていなかったのと、二人の開発スピードが落ちていったことで、やがて開発者が離れていく傾向にありました
  • 2007/06/29 に開発の終了が発表されました。(http://snipsnap.org/comments/start/2007-06-29/1)
  • 同じエントリのコメント欄にて aos さんが中心になって SourceForge で開発しようぜという話になりました (僕だけ自分のサイトの宣伝してるんで申しわけないw。いやほんと公開するつもりなんですよー)
  • 実は以前にもユーザのつぎあげがあって SourceForge にプロジェクトが作られたことがあるのです。SnipSnap on SF 残念ながら全く更新されず死にプロジェクトになっています
  • 管理者は SnipSnap のコミッタ二人なのですが、彼等に連絡が取れないのでプロジェクトにアクセスすることができませんでした
  • 仕方なく他の名前でプロジェクトを立ち上げることになり、aos さんが SnipSnip プロジェクトを立ち上げました (スニップス *ニ* ップです)
SnipSnip

今後ですが、まずは SnipSnap 最終版のコードに対して、いろんな人が独自に拡張していたコードをマージしていくことになるんじゃないかと思います。

開発に参加したい方は aos さんに連絡取ってみてください。

Author:akira 9:36:04 PM Comments (2) Trackbacks (0) Tags: java snipsnap
10/21/07
AO#6 Name Converter
今回は An Easier Java ORM Part 4 の Pluggable Name Converters を見ていきます。テーブルとエンティティクラスのマッピングの話題です。

名前のマッピング方法はデフォルトでは Camel Case 方式 (実際には先頭を小文字にするだけ) です。例えば BillingAddress クラスなら billingAddress テーブルが作成されます。

@Table アノテーションを使って明示的にテーブル名を指定することもできます。

@Table ("PERSON_TBL")
public class Person {
…
}

名前変換は TableNameConverter を実装するクラスが担当していて、取り替えができる (pluggable) ようになっています。EntityManager に対して setNameConverter で実装クラスを渡してやります。

manager.setNameConverter(new MyNameConverter());

元記事には、自分で作る場合は AbstractTableNameConverter を継承するのがお勧めとありますが後述する PluralizedNameConverter に特化したような処理が含まれるので、自前で TableNameConverter を実装した方が手っ取り早いと思います。

その場合、上記の @Table の処理を実装しておいた方がいいでしょう。下記のコードを含むだけで良いです。

Table tableAnnotation = entity.getAnnotation(Table.class);
		if (tableAnnotation != null) {
			return tableAnnotation.value();
		}

English Pluralization ActiveObjects にはデフォルトの CamelCaseTableNameConverter の他に英単語の複数形を考慮に入れた PluralizedNameConverter が用意されています。語尾に s を付けるだけでなく Person -> people のような特殊なものまでサポートされています。

試してみました。

em.setNameConverter(new PluralizedNameConverter());
em.migrate(Cactus.class);

こんなテーブルが作成されました。

CREATE TABLE cacti (
    id INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(45),
    PRIMARY KEY(id)
) ENGINE=InnoDB

サボテンクラスってのも変な話ですが、ちゃんと変換されてることが確認できました ;-p

実装としては変換ルールを書いたプロパティファイルを使って変換しています。net/java/ao/schema/englishPluralRules.properties を見れば変換の仕組みがわかると思います。

10/15/07
AO#5 Schema Generation
今回は An Easier Java ORM Part 4:http://www.codecommit.com/blog/java/an-easier-java-orm-part-4 の Schema Generation の項を読んでみます。(というかあまり本文に沿ってないけど、、、まとめてみます)

スキーマ生成

ActiveObjects にスキーマ (DDL) を作成してくれる機能があります。ちゃんと関連を考慮して外部キーを作ってくれるのに加えて、アノテーションでいろいろと指示することができます。次のコードが例として挙げられています。
public interface Person extends SaveableEntity {
    public String getFirstName();
    public void setFirstName(String firstName);

@Unique @SQLType(precision=128) public String getLastName();

@Unique @SQLType(precision=128) public void setLastName(String lastName);

@SQLType(Types.DATE) public Calendar getBirthday(); @SQLType(Types.DATE) public void setBirthday(Calendar birthday);

@Accessor("url") public URL getURL(); @Mutator("url") public void setURL(URL url); }

この例で getter と setter の両方に同じアノテーションが付いているのがわかると思います。これは java.lang.Class.getMethods() の戻り値配列で先に現われる方のアノテーションだけを使う仕様になっているためです。Java 仕様では戻り値の順序は保証されていません。したがってアノテーションは getter と setter の両方に同じものを付ける必要があります。(もしくは片方に @Ignore を付けます)

アノテーションの種類には以下のものがあります。

  • Mutator
  • Accessor
  • OneToMany
  • ManyToMany
  • Ignore
  • SQLType
  • PrimaryKey
  • NotNull
  • Unique
  • AutoIncrement
  • Default
  • OnUpdate
役割はだいたい想像できると思いますが、少しピックアップしてみます。

Accessor/Mutator

ActiveObjects は getXXX や isXXX または setXXX が getter、setter を自動的に判別しますが、これらのアノテーションにより明示的に getter setter を指定することができます。また getXXX などの場合でもデータベースの列名が意図通りにならないことを避けるために用います。上記の getURL がこの例で、@Accessor を付けないと デフォルトの名前マッピングアルゴリズムでは uRL という列名になってしまいますので url を明示的に指定しています。

SQLType

Java <-> SQL の型マッピングは自動的に解決されます。(マッピングは java.ao.types 以下で定義されています。) 自動のマッピングが不適切な場合や precision や scale まで指定したいときに SQLType アノテーションで明示的に指定することができます。 value には java.sql.Types の値を指定します。
@SQLType(value=Types.INTEGER, precision=5, scale=0)
int getCount();

OnUpdate

更新時に設定される値を指定します。MySQL では ON UPDATE、Oracle の場合はトリガとして定義されます。 MySQL の場合は指定できるのは次のいずれか。
  • CURRENT_DATE
  • CURRENT_TIMESTAMP
Oracle などいくつかのデータベースの場合は任意の値が指定できるようです。(ソースコード見てる分にはできそうですが試していません)
10/1/07
ActiveObjects おためし#4
それでは今日は An Easier Java ORM Part 3 (http://www.codecommit.com/blog/java/an-easier-java-orm-part-3) を読んでみます。

この回のネタは

  • サポート対象データベース
  • トランザクション
です。

サポート対象データベース

正式サポートはこちら。
  • Derby (standalone and embedded)
  • MySQL
  • PostgreSQL
  • Oracle (with the limitation that @AutoIncrement is only supported on primary keys)
ほとんどテストされてないけどプロバイダクラスは用意されてるよってのがこっち。
  • Microsoft SQL Server (Microsoft and JTDS providers)
  • HSQLDB (standalone and embedded)
ActiveObjects の利用シーンを考えると HSQLDB は結構ありそう (特に開発中) なので正式にサポートしてもらえるとうれしいですね。このへんは JSE6 になれば Derby 一色になってりするんだろうか。(OSX 版早く出てこい)

トランザクション

では続いてトランザクション。

トランザクションは net.java.ao.Transaction クラスの run を実装して定義します。Transaction#execute() は下記の処理を実行します。run メソッド内が一つのトランザクションになります。

  1. getConnection()
  2. run() の中を実行
  3. commit()
サンプルはこちら。

new Transaction(manager) {
    public void run() {
        Account david = getEntityManager().get(Account.class, 1);
        david.setValue(david.getValue() - 1000);
        david.save();
?
        Account mary = getEntityManager().get(Account.class, 2);
        mary.setValue(mary.getValue() + 1000);
        mary.save();
    }
}.execute();

ブログエントリには execute() のかわりに executeConcurrently() を実行しているサンプルもありますが、このメソッドはバージョン 0.5 にはありません。(どこで存在したか不明。ただの例かな?)

今回はここまで。

9/27/07
ActiveObjects おためし#3
今日は An Easier Java ORM Part 2 (http://www.codecommit.com/blog/java/an-easier-java-orm-part-2) を読んでみます。

内容は SaveableEntity と Implementations です。

SaveableEntity

SaveableEntity はバージョン 0.5 でなくなってます。理由はこっちのエントリ SaveableEntity Bids a Fond Farewell (http://www.codecommit.com/blog/java/saveableentity-bids-a-fond-farewell) に書いてあります。要は普通 SaveableEntity を使うからそれをデフォルトにしたってことのようです。

バージョン 0.5 より前だと Entity の setter を呼ぶたびに UPDATE 文が発行されていたようで、SaveableEntity を使えばそれらを一回の UPDATE 文にまとめることができたとのこと。0.5 以降の Entity はこの動作になりました。

ブログエントリにあるサンプルコードで言えば、こんな Entity があって

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
    public String getLastName();
    public void setLastName(String lastName);
}

下記のコードで setter を 2 つ呼んでみます。

private void initializePerson(EntityManager em, String name) throws SQLException {
    String[] names = name.split(' ');
    Person p = em.create(Person.class);
    p.setFirstName(names[0]);
    p.setLastName(names[1]);
    p.save();
}

結果はこうなります。

INSERT INTO person (id) VALUES (DEFAULT)
UPDATE person SET firstname = ?,lastname = ? WHERE id = ?

UPDATE 文は 1 回だけ、save() の段階で実行されます。

Implementations

では続いて Implementations。ActiveObjects ではエンティティをインタフェースとして宣言するので、そのままではエンティティ自体にロジックを持たせることができません。そこで実装クラスを明示的に指定する機能が用意されています。@Implementation アノテーションで指定します。

ブログエントリのサンプルを見てみます。User クラスの setPassword() にクリアテキストを渡すと MD5 のハッシュがデータベースに登録される仕掛けです。

まず Entity の宣言。(ブログエントリの方は extends SaveableEntity になってますが、前述の通りなくなったので Entity に書きかえています)

@Implementation(UserImpl.class)
public interface User extends Entity {
    public String getUsername();
    public void setUsername(String username);

public String getPassword(); public void setPassword(String password); }

対応する実装クラスを書きます。

public class UserImpl {
    private User user;

public UserImpl(User user) { this.user = user; }

public void setPassword(String password) { user.setPassword(Utilities.md5sum(password)); } }

Utilities は自前のユーティリティクラスです。(適当に作ってください)

実行はいつもどおりに。

// …
User u = em.create(User.class);
u.setUsername(“daniel“);
u.setPassword(“password“);
u.save();

System.out.println(u.getPassword()); // prints the MD5 hashed value of “password“

最後の getPassword() で MD5 でハッシュ化された値が取得できます。

このあたりは下記要領で行われます。

  1. EntityManager がエンティティインタフェースのプロキシを作成する
  2. @Implementation があれば
    1. エンティティのインスタンスを引数にして実装クラスのコンストラクタ (例: UserImpl(aUser) ) を呼ぶ
    2. init() があれば呼ぶ
  3. エンティティ (実体はプロキシ) のメソッドが呼ばれると
    1. 実装クラスに該当メソッドが実装されている場合はそれを呼ぶ。
    2. 実装クラスがなかったり、メソッドが実装されていない場合はプロキシ側で対応する。setter なら save() 時のデータベース更新のために値を保存しておく。getter なら保存されている値を返す
実装クラスの要件は下記となります。
  • エンティティのインスタンスを受け取るコンストラクタを用意する
  • setter でエンティティの setter を呼んで値をセットしておく
実装を変更したいメソッドのみ実装すれば OK です。
Author:akira 12:08:49 AM Comments (0) Trackbacks (0) Tags: activeobjects java
9/25/07
ActiveObjects おためし#2
しばらく時間があいてしまいました。これも全部 civ4 のせいです><)

さて今日は前回に引き続き An Easier Java ORM (http://www.codecommit.com/blog/java/an-easier-java-orm) を見ていきます。今回は関連です。

ActiveObjects で関連を表現するにはアノテーションを使うようです。それだけでなくメソッドの名前が重要みたいです。ActiveRecord と一緒ですね。サンプルに出ているのはコレ。Person 側に House への関連を示すメソッド(getHouse, setHouse)が定義されています。House 側も getPeople というのがありますね。Person の複数形で People です。@OneToMany アノテーションも付いてます。

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
    public House getHouse();
    public void setHouse(House house);
}

public interface House extends Entity { public String getAddress(); public void setAddress(String address); @OneToMany public Person[] getPeople(); }

とにかく試してみます。

EntityManager em = new EntityManager(“jdbc:mysql://localhost/ao“, “akira“, “akira“);
Logger.getLogger(“net.java.ao“).setLevel(Level.FINE);
House house = em.create(House.class);

house.setAddress(“Tokyo“);

Person p1 = em.create(Person.class); p1.setFirstName(“akria“); p1.setHouse(house);

Person p2 = em.create(Person.class); p2.setFirstName(“taro“); p2.setHouse(house);

house.save(); p1.save(); p2.save();

住所を Tokyo とする House オブジェクトを作って Person akira, taro にそれぞれ setHouse します。

実行すると MySQL には下記のデータが入ります。

mysql> select * from house;
+----+---------+
| id | address |
+----+---------+
|  1 | Tokyo   | 
+----+---------+

row in set (0.00 sec)

mysql> select * from person; +----+-----------+---------+ | id | firstName | houseID | +----+-----------+---------+ | 1 | akria | 1 | | 2 | andy | 1 | +----+-----------+---------+ 2 rows in set (0.00 sec)

Person からは foreign key の houseID で House を参照してますね。このときのログはこちら。

2007/09/25 0:57:01 net.java.ao.DatabaseProvider executeInsertReturningKeys
情報: INSERT INTO house (id) VALUES (DEFAULT)
2007/09/25 0:57:01 net.java.ao.DatabaseProvider executeInsertReturningKeys
情報: INSERT INTO person (id) VALUES (DEFAULT)
2007/09/25 0:57:01 net.java.ao.DatabaseProvider executeInsertReturningKeys
情報: INSERT INTO person (id) VALUES (DEFAULT)
2007/09/25 0:57:01 net.java.ao.EntityProxy save
情報: UPDATE house SET address = ? WHERE id = ?
2007/09/25 0:57:01 net.java.ao.EntityProxy save
情報: UPDATE person SET firstname = ?,houseid = ? WHERE id = ?
2007/09/25 0:57:01 net.java.ao.EntityProxy save
情報: UPDATE person SET firstname = ?,houseid = ? WHERE id = ?

INSERT と UPDATE が実行されていますね。EntityManager#create 時に INSERT 文が実行され、Entity#save 時に UPDATE が実行されます。

では今度は getPeople のテスト。

House h = em.get(House.class, 1);
for (Person p : h.getPeople()) {
    System.out.println(p);
}

さっき作った House のプライマリキーが 1 なので、それを指定して get します。そのあと getPeople してます。

System.out.println の出力はこちら。

person {id = 1}
person {id = 2}

これらは Person の Proxy が出力しています。

ログ出力はこちら。

2007/09/25 1:08:39 net.java.ao.EntityProxy retrieveRelations
情報: SELECT id FROM person WHERE houseID = ?

ちゃんと動いてますね。

House インタフェースの getPeople は ActiveRecord ならデフォルトではこの名前でなければいけなかったと思いますが、ActiveObjects ではどうなのかな? 試してみます。

これでどうだ。

@OneToMany
public Person[] get人();

エラーになるかなと思ったけど実際には結果は変わりませんでした。まぁシグネチャで判断できるしね。

9/19/07
ActiveObjects おためし#1
ActiveObjects (https://activeobjects.dev.java.net/) に興味が出てきました。まだ情報がほとんどなくって、公式ページにあるサンプル dogfood blog は svn でアクセスするとパスワード聞かれるし、よくわかりません。

どうやら作者さん(?) のブログ (http://www.codecommit.com/blog/) が詳しそう。 そこで、とっかかりとして、An Easier Java ORM (http://www.codecommit.com/blog/java/an-easier-java-orm) を読んでみます。(このエントリは ActiveObjects 0.5 を使って動作を検証しています)


要するに Rails の ActiveRecord みたいなものを Java で実装したのが ActiveObjects のようです。AR のシンプルで速く開発できる点を評価しているみたいです。

AR の例としてこんなのが挙げられています。(元のブログより引用)

class Person < ActiveRecord::Base
end

puts Person.find(1).first_name

僕は Rails の入門本を読んだくらいしか知りませんし Ruby もほとんどわからないのですが、Ruby には存在しないメソッドをトラップする機構があって、それで first_name なんていう未定義のメソッドをうまく処理できるとのこと。でも Java 使いからすれば型安全性だとかコンパイル時の静的チェックだとかが気にならなくもないです。

で、上記のコードと同等のことを ActiveObjects でやるとこんな感じらしいです。(元のブログより引用)

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
}

EntityManager em = new EntityManager(jdbcURI, username, password);

Person p = em.get(1); System.out.println(p.getFirstName());

クラス、メソッド定義をちょいはしょってるのでこのままじゃあ動きませんが、雰囲気はわかりますね。

最初 4 行がエンティティ Person の宣言。ActiveObjects ではエンティティをインタフェースとして宣言します。普通の POJO (ってのも変な言いまわしか) みたいにクラスではありません。これには賛否あるようでコメント欄に書かれていますが、Java の Proxy の仕組みがインタフェースのみが対象とするためインタフェースにしているそうです。cglib 等を使えばクラスも対象にできるらしいので将来的にはクラスも使えたりするのかもしれませんね。

また、Entity インタフェースを継承する必要があります。これについてもコメント欄でアノテーション (@Entity とか) を使わないのはなぜかとありますが、getID(), setID() なんかのメソッド宣言を継承するためとのこと。

ポイントはこのへん。

  1. Entity を継承してインタフェースを宣言する
  2. インタフェースでは getter/setter を宣言する
EntityManager em = … 以降の行がデータベースとやりとりする部分です。実際にはどこかのメソッド内で書きます。まぁあたりまえだけど。 ちなみに EntityManager は JPA のものじゃなくて ActiveObjects 独自クラスなので JPA の方を import してしまわないように注意かな。

MySQL だとこんなコードになります。

EntityManager em = new EntityManager(“jdbc:mysql://localhost/ao“, “akira“, “akira“);

それで次の em.get(1) ですが、これはたぶん間違い。少なくともバージョン 0.5 にこんなメソッドはありません。あるのは

public <T extends Entity> T get(java.lang.Class<T> type, int id)

なので、

Person p = em.get(Person.class, 1);
と書かないといけないです。あ、第 2 引数の 1 はプライマリキーです。

さて実行前にテーブルを作っておく必要があります。手動で作ってもいいけど自動でも作れます。ブログに書いてある Generator.generate() メソッドはバージョン 0.5 には存在しません。かわりに migrate() なら動きます。(ドキュメントに書いてあったわけじゃないので確証はないです)

Generator.migrate(new MySQLDatabaseProvider(“jdbc:mysql://localhost/ao“, “akira“, “akira“), Person.class);

(2007/09/20 追記) EntityManager.migrate() の方が簡単みたいです。

EntityManager em = new ....
em.migrate(Person.class);

実行すると下記のようなテーブルを作ってくれます。

CREATE TABLE person (
    id INTEGER AUTO_INCREMENT NOT NULL,
    firstName VARCHAR(45),
    PRIMARY KEY(id)
) ENGINE=InnoDB

あと、レコードを 1 行 insert しておきます。

insert into person values (1, 'akira');

それでは実行してみたいと思いますが、ActiveObjects が実行する SQL 文を表示させる方法があるので設定しておきます。ActiveObjects では Java Logging API を使って net.java.ao の Logger に対し FINE で出力してます。理由がわからなかったのですが、EntityManager の static イニシャライザで無効にしているらしく、EntityManager をロードして (使って) から改めて設定してやる必要があります。

logging.properties

handlers= java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
.level = FINE
net.java.ao.level = FINE

JVM 起動引数

-Djava.util.logging.config.file=logging.properties

ソースコード

EntityManager em = new EntityManager(“jdbc:mysql://localhost/ao“, “akira“, “akira“);
Logger.getLogger(“net.java.ao“).setLevel(Level.FINE);

無理矢理だけどこれでまぁ出力されるので良しとしよう。 (詳しくは EntityManager のリファレンスを参照してください)

いよいよ実行です。

getFirstName() の結果 'akira' が取得できました。ログにはこんなのが出力されます。

SELECT firstName FROM person WHERE id = ?

なるほど。

このブログエントリにはまだ続き (relation とか) があるけど、今日はこのへんで。

なかなか面白そうだなー。

Author:akira 12:32:14 AM Comments (0) Trackbacks (0) Tags: activeobjects java