2008年11月27日木曜日

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(9)

今度はテーブルの内容を一覧表示します。

■EJB(MySampleSession)に一覧(java.util.List)を取得するメソッドを追加します。
    // List<MySample>のwarningを抑止しています。それ以外は来ないはずなので。
@SuppressWarnings("unchecked")
public List<MySample> listMySamples() throws MySampleException {
Query query = em.createQuery("select m from MySample m");
List<MySample> result = query.getResultList();
return result;

}

■Webプロジェクト(MySampleJSF)に、新規にListBeanを追加します。
package test.beans;

import java.util.List;

import javax.ejb.EJB;

import test.MySample;
import test.MySampleSessionLocal;

public class ListBean {
private static final long serialVersionUID = 1L;
/*
* JPA直は好きじゃないのですが今回はこれで。
*/
List<MySample> mySamples = null;

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public List<MySample> getMySamples() {
// nullチェックでは厳密にインスタンスの生成を制御できませんが、
// まあ二回くらい呼ばれたっていいでしょう
if (mySamples == null) {
try {
List<MySample> tmpList = mySampleSession.listMySamples();
setMySamples(tmpList);
} catch (Exception e) {
//
}
}
return mySamples;
}

private void setMySamples(List<MySample> mySamples) {
this.mySamples = mySamples;
}
}

■faces-config.xmlにmanagedBean要素を追加します。
  <managed-bean>
<managed-bean-name>listBean</managed-bean-name>
<managed-bean-class>test.beans.ListBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

■list.jspを新規に作成します。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><html>
<head>
<title>list</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
<h2>リスト MySample</h2>
<f:view>
<h:dataTable value="#{listBean.mySamples}" var="item" border="1">
<h:column>
<f:verbatim>id: </f:verbatim>
<h:outputText value="#{item.myid}"/>
</h:column>
<h:column>
<f:verbatim>value: </f:verbatim>
<h:outputText value="#{item.myFlag}"/>
</h:column>
</h:dataTable>
</f:view>
</body>
</html>

今度は一覧表示にラジオボタンを追加したいのですが、これが大変なのです(<h:dataTable ..>と<h:selectOneMenu...>は入れ子にできないため・・・)。次回以降で挑戦してみます。

以上
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(8)

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(8)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)
(前回)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)
(今回はここまで)
12. 未定。テーブルの内容の一覧表示とか

後は似たようなものです。どんどん行きます。

10. EJBに削除メソッドを作成する

■MySampleSessionにロジックを追加します。
    public void deleteMySample(int myid) throws MySampleException {
MySample target = this.findMySample(myid);
if (target == null) {
throw new MySampleException();
}
em.remove(target);
em.flush();
}

以上。UTCなどで動作確認することもできます。

11. JSFを作成(削除)

■MySampleBeanにロジックを追加します。
    public void deleteMySample(int myid) throws MySampleException {
MySample target = this.findMySample(myid);
if (target == null) {
throw new MySampleException();
}
em.remove(target);
em.flush();
}

JSPは全てこれまでのものを流用します。
■success.jspに削除ボタンを追加します。
Found bean.<br>
id -> ${ mySampleBean.id } <h:inputHidden value="#{mySampleBean.id}"/>
value -> <h:inputText value="#{mySampleBean.value}"/>
<br>
<h:commandButton value="更新"
action="#{mySampleBean.updateValue}" />
<h:commandButton value="削除"
action="#{mySampleBean.deleteValue}" />

■faces-config.xmlを編集します(削除が成功したら検索画面に戻ります)。
  <navigation-rule>
<from-view-id>success.jsp</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/WEB-INF/results/success3.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>del_failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>del_success</from-outcome>
<to-view-id>/search.jsp</to-view-id>
</navigation-case>
</navigation-rule>

以上。
.

2008年11月26日水曜日

痛恨の片思い

一方的に仲良くしたい、親しみたいと思っていろいろアプローチしても、どうも相手のほうはその気になってくれないというか、うまく行かないということはよくありますが、私の場合、そのお相手は豚バラブロックの大きなかたまり肉でした。

昔からどうもこのほとんど脂身じゃねーかコノー、という巨大なかたまりに対しては、憎しみと共に愛情、あるいはほのかな憧れを抱いていたのです。憎たらしい脂身だけれども、いったいどうやったらこれを美味しく頂けるんだろう。スーパーでカナダ産やアメリカ産の豚バラブロック肉を見るにつけ、なんだか挑発されているような煽られているような気がしてならなかったのです。

妻は飽和脂肪酸とか動物性油脂や加工油脂とかを嫌がるので、ブロックだろうが薄切りだろうが豚バラ肉を嫌います。実は私だって脂身はさほど好きではない。豚ならバラよりヒレ肉。鳥ならモモ肉よりもムネやささみを好むほうです。しかしどうにもこの白い脂のかたまりは、私の本能を突き動かしてしょうがない。DNAレベルで揺さぶられている気すらしてしまう。

一部で話題の飽和脂肪酸。体によくないらしいけれども、沖縄では皮付きの豚ばら肉を泡盛で煮込んで黒糖としょうゆで煮付け、美味しい角煮を作っているらしい。つまり、沖縄では豚バラの角煮が食べられている。しかるに沖縄は長寿で有名である。すなわち豚バラの角煮を食べているにも関わらず、沖縄の人は長生きする。つまり、角煮を食べてもそれほど体に悪いことはないかしんない、という三段論法がここに成立するわけです。

昔テレビでやっていた「どっちの料理ショー」でも、よく肉からタラーリタラリと垂れる脂を見て歓声が上がっていたような気がします。しかも脂をたっぷり口に含んで「ジューシーで美味しい!」とか「甘~い」とか。脂舐めてうまいとは何ごとであるか、と半分怒りながらも見ていた私でしたが、豚ばら肉のレシピを見ると「最初にしっかり焼いて余分な脂を落とす」とか「酒を入れたお湯でしっかり茹でてから調理する」という記載があり「余分な脂が抜けて*サッパリした*美味しい豚バラの角煮」というものが存在しているかのように信じてしまい、いつかはそのような角煮を作って見たいものだ、などと考えていました。

で、一度作ってみたんですよ。もうしばらく昔になりますけど。しっかり焼いて脂も落としたし(60%くらいの大きさに縮まった)、味つけする前にお湯で1時間以上茹でたりもしました。でも、結果はやっぱり豚の脂。脂は脂。冷えるとにっちゃり。確かに美味しかったですけどね。でもニチャニチャ。

これに懲りてしばらくこの人には手を出さなかったんですが、またこの間また挑戦してみたのです。塩豚に。しかも塩豚を燻製にして自家製ベーコン を作ってみようと。よりによってというかアチャーという行為ですが、片思いから逃れられない私。恋は盲目です。

結論から言いますと、これが大失敗。いや、多分料理としては正当な手順でそこそこ正当な結果が得られたと思うんですが、その出来上がったものがまさに煙で燻されたしょっぱい豚脂。もう一口で勘弁って感じでした。頑張って半分ほど使いましたが、一週間ほど経過して消費できなかった残りは迷わずゴミ箱へダンクシュート。普段は食べ物を捨てるなんてことはしないんですよ。賞味期限+1、2日経過のものは平気だし、ものによっては味噌や塩に漬け込んで延命を図り、ちゃんと消費する性格です。食べ物は粗末にしたくない。でも塩豚の燻製はアウトでしたね。もう二度と作らない。

というわけで、ようやく豚バラの呪いから開放されたと思った私ですが、この前、業務用スーパーで巨大な豚バラかたまり肉(2,3kgもあろうかというやつ)を見かけて瞳孔を拡張しながら足を止めてしまいました。なんて懲りない私でしょうか。もう二度と自分で買うことはないでしょう。ないと思います。しかし、この豚バラのかたまりは、当分の間私を悩ませ続けるに違いない。巨大な生白いエロティックな脂肪の塊から目を離すことができないまま、私はそのように思ったのであります。

以上。
.

2008年11月25日火曜日

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(7)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
(前回)
9. JSFを作成(更新)
(今回はここまで)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)

9. JSFを作成(更新)

JSFに更新ページを作成します。

■MySampleBeanにロジックを追加します。
 public String updateValue() {
try {
mySampleSession.updateMySample(id, value);
} catch(Exception e) {
return "failure";
}
return "success";
}

これだけ。

■次はJSP。
以前に作った検索(search.jsp)、結果表示ページ(/WEB-INF/results/success.jsp)を再利用します。

まず旧結果表示ページを/WEB-INF以外の場所に移動し、編集します。
なぜ移動するか。
以前に紹介したチュートリアルのPage-Navigation-1.pdfに以下の記述がありました。
Strategies
- You cannot put input-form JSP pages in WEB-INF
- Because URL must correspond directly to file location

そのまんまですね。この人はJSFの欠陥だ、と言い切ってます。私もそう思うな。

idはそのまま表示し(hidden要素に入れておく)、valueはテキストボックスに表示します。
Found bean.<br>
id -> ${ mySampleBean.id } <h:inputHidden value="#{mySampleBean.id}"/>
value -> <h:inputText value="#{mySampleBean.value}"/><br>
<h:commandButton value="更新"
action="#{mySampleBean.updateValue}" />

こんな感じで。

次に新しい方の結果表示ページ(更新結果を表示するページ)を作成します。
/WEB-INF/results/success3.jspとします。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Updated bean.<br>
id -> ${ mySampleBean.id }
value -> ${ mySampleBean.value }
</body>
</html>

次にfaces-config.xmlです。以下のタグを適切な場所に追加します。
  <navigation-rule>
<!-- この success.jsp が /WEB-INF/results の下にあるとダメな分けです -->
<from-view-id>success.jsp</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/WEB-INF/results/success3.jsp</to-view-id>
</navigation-case>
</navigation-rule>

以上。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(6)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
(前回)
8. EJBに更新メソッドを作成する
(今回はここまで)
9. JSFを作成(更新)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)

8. EJBに更新メソッドを作成する

EJBに更新メソッドを作成します。

以下のメソッドをMySampleSession セッションBeanに追加します。
 public void updateMySample(int myid, String value) throws MySampleException {
if (value.length() > 1) {
throw new MySampleException();
}
MySample target = (MySample)em.find(MySample.class, myid);
if (target == null) {
throw new MySampleException();
}
target.setMyFlag(value);
em.persist(target);
em.flush();
}

アウトラインでupdateMySampleメソッドを右クリックし、Java EE ツール > メソッドのプロモート を実行します。(忘れがちなので注意しましょう)

これでUTCからテストが出来ます(テスト方法このシリーズで何度か書いたので割愛します)。ちゃんと動くか確認してみて下さい。(サクサク行きますねえ)
.

プリキュア映画版は面白かった

やはり面白いですね。映画版プリキュア。普段は地味な主役もちゃんと活躍してたし。カッコよかったぜ、ていい歳ぶっこいて何言ってんだ、という照れもありつつも。

やはりおっさんが若い女子の活躍する熱血青春アニメを面白がるというのも恥ずかしいもんで、そこは勘弁して頂きたい。

しかし、今回は結構感情移入して見て楽しかったですよ。これまでは「よく出来ている」「面白い」とは思いつつも、客観的スタンスを崩していなかったのが、映画では結構引き込まれた。どうしてかな。悪役がどっかマヌけなモチベーションを持っていたのが良かったと思うな。

まあ、小さい子供を持つお父さんもぜひ一緒に楽しんできてください。面白いから。多分ね。

.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(5)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
(前回)
7. JSFを作成(挿入)
(今回はここまで)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)

7. JSFを作成(挿入)

挿入を受け付けるJSF画面を追加します。(行き当たりばったりの画面設計・・・)

JSFの観点から言えばNothing Specialです。淡々と行きます。

■insert.jsp
<%@page language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>挿入</title>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-31j">
</head>
<body>
<CENTER>
<h2>挿入</h2>
<h:form>
myid:
<h:inputText value="#{mySampleBean.id}" />
value:
<h:inputText value="#{mySampleBean.value}" />
<h:commandButton value="挿入"
action="#{mySampleBean.insertValue}" />
</h:form>
</CENTER>
</body>
</html>
</f:view>

■/WEB-INF/result/failure2.jsp(重複キーエラーの時に表示させます)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Duplicate key exists. Could not insert.
</body>
</html>

■/WEB-INF/results/failure2-1.jsp(その他のシステムエラー用です。UTできませんが念のため)

/WEB-INF/result.failure2.jspの"Duplicate key exists. Could not insert."を"System error"に変えるだけ

■/WEB-INF/reusults/success2.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Inserted bean.<br>
id -> ${ mySampleBean.id }
value -> ${ mySampleBean.value }
</body>
</html>

■faces-config.xml
以下を追加
  <navigation-rule>
<from-view-id>/insert.jsp</from-view-id>
<navigation-case>
<from-outcome>failure2</from-outcome>
<to-view-id>/WEB-INF/results/failure2.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure2-1</from-outcome>
<to-view-id>/WEB-INF/results/failure2-1.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success2</from-outcome>
<to-view-id>/WEB-INF/results/success2.jsp</to-view-id>
</navigation-case>
</navigation-rule>

■MySampleBeanに太字部分を追加
package test.beans;

import java.io.Serializable;

import javax.ejb.EJB;

import test.MySample;
import test.MySampleException;
import test.MySampleSessionLocal;

public class MySampleBean implements Serializable {

private static final long serialVersionUID = 1L;

int id;
String value;

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}

public String checkInput() {
MySample ms = mySampleSession.findMySample(id);
if (ms != null) {
this.setValue(ms.getMyFlag());
return "success";
} else {
return "failure";
}
}

public String insertValue() {
try {
mySampleSession.addMySample(id, value);
} catch(MySampleException mse) {
return "failure2";
} catch(Exception e) {
return "failure2-1";
}
return "success2";
}
}

以上です。いや、簡単ですね。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(4)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
(前回)
6. EJBに挿入メソッドを作成する
(今回はここまで)
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)

6. EJB Session Beanに挿入メソッドを作成する
findメソッドの次にinsertMySampleメソッドを作成します。

最初に例外を追加します。想定していないデータが入力されたときにスローするためです。

MySampleEJBClientフォルダ(注意!EJBClientフォルダです) < ejbModule < test パッケージを右クリック < 新規作成 < クラス として「新規Javaクラス」ウィンドウを起動します。名前に「MySampleException」スーパークラスに「java.lang.Exception」を指定します。以上です。

MySampleEJBプロジェクト < MySampleEJB < セッションBean < MySampleSession.java を開きます。

以下のメソッドを追加します。
    public void addMySample(int myid, String value) throws MySampleException {
if (value.length() < 1) {
throw new MySampleException();
}
try {
MySample ms = new MySample();
ms.setMyid(myid);
ms.setMyFlag(value);
em.persist(ms);
em.flush(); // これがないと例外がキャッチできません。重要!
} catch(EntityExistsException e3) {
throw new MySampleException();
}
}

em.flush()が重要です。これをしないとアプリケーションから到達できないクラスで例外が発生するため、ハンドリングができなくなります。

次にメソッドのプロモートを忘れずに実行します。(アウトライン ビューでaddMySampleメソッドを右クリック、Java EE < メソッドのプロモート)

WAS v7テスト環境を起動します。

サーバーを右クリックしてUniversal Test Clientを起動、ログインします。

1.JNDI エクスプローラーリンクをクリック
2.右ペインに表示される[ローカル EJB Bean]フォルダを展開
3.test.MySampleSessionLocalリンクをクリック
4.左ペインに表示されるMySampleSessionLocalの'+'を展開
5.void addMySample(int, String) をクリック
6.int と String(1文字のみ) に適宜値を入れて起動

「メソッドが正常終了しました。」と表示されれば成功です。テーブルの中を見るとデータが追加されていることが確認できます。

6のステップで二文字以上を入力し、例外のロジックを確認します。MySampleExceptionが発生すれば成功です。

.

2008年11月22日土曜日

買出しは楽し

本日、朝からわが家の子供たちがおばあちゃん(義母)のところに遊びに行きました。妻も外出。すなわち私は半日の自由をゲット。

というわけで以前から気になっていた練馬の城北流通センター(大江戸河岸城北卸売市場)に行ってきました。Webにはほとんど情報はありません。それでも頑張って(というかダラダラ?)調べたところ、どうやら「安いらしい」「プロ用の店らしい」「でも一般客も歓迎らしい」「定休日が不明。営業時間はAM6:00~午前いっぱいらしい」とのこと。果たして土曜日は営業しているのか。無駄足となる懸念はありつつも、安くて新鮮な魚が手に入るのでは、と期待して朝9:00頃出かけてみました。

寒い中、リュックを担いで自転車で遠征。環八(笹目通り)から練馬高野台方面に入って目的地に到着。大丈夫。ちゃんと営業してました。

自転車置き場にはママチャリが10~20台ほど並んでます。結構一般の人も来てるのかな。自転車を止めて恐る恐る入ってみました。子連れのお父さんを何人か確認。一般人も普通に来ているようです(実はプロかもしれないけどね)。ざっと周りを散歩。そんなに広くはありません。中堅スーパーくらいかな。昔の魚屋さんとか乾物屋さんという店が並んでます。ダンボールや発泡スチロールが通路にせり出している。市場(いちば)って感じがします。でもちょっと活気がないか。全体に高齢化している模様。

一番元気なのが入り口近くの魚屋さんです。元気なおばさんと若いあんちゃんが店先で仕事してます。おばさんが主に客の相手をしていて、あんちゃんは力仕事担当。店の奥ではおっさんが黙々と魚を捌いている。うん。好ましいなー。なぜだか昭和の感じがする。

発泡スチロールの中には魚が氷に埋もれています。サンマ、サバ、アジ、太刀魚、キンメ、イカ、スズキ。いいねえ。値札を見るとサンマ一本80円とある。まあまあだな。子供の手のひら大の小アジ一匹70円。う~ん、ちょっと小さすぎる。アジの中くらいのがグラム150円(うろ覚え)。グラムじゃあ安いんだか高いんだか分からない。でも値札にご丁寧に「今日は高いです!」と書いてある。

「高い!」はないだろうと不審に思っていたら、あんちゃんが別の客に説明しているのが聞こえてきました。「今日はシケだったから高いよ~。それに量もなくてね~」。

はたと気がつく。そうか。この「高い!」は不本意の「高い!」だったのか。安くて新鮮な魚を期待するお客さんに申し訳ない、普段はもっと安いんだという忸怩たる「高い!」だったのだ。う~ん。ますます好ましい。というわけで「サンマ5本くださーい」とおばちゃんに言ってみる。一本は刺身に、残りの4本はパン粉焼き+自家製ピクルスのタルタルソースにしよう。サンマを5本袋に詰めてもらって支払い。「月曜はやってますか?」とおばちゃんに聞いたら「カレンダー通りだから休みなのよ。ごめんね」とのこと。了解。また来週来てみよう。

それから野菜を仕入れにスーパーに行きました。その前にTully'sに寄って熱いコーヒーを一杯。本日のコーヒー/ショートサイズ290円。こんなに高かったっけ?でもコーヒーは美味い。

スーパーでまずは野菜売り場に。葉尽きの大根、小松菜、ほうれん草、にんじんを買い物カゴへ投入。大根の葉っぱは茹でて刻んでしょうゆと削り節と砂糖少々で炒めると旨いのですよ。大根本体はどうやって食べようかと悩んでいたら、養殖鯛のおかしらが目に留まりました。つぶらな瞳が僕を見ている。しばらく目を合わせていると「こいつと大根を酒と薄口しょうゆで煮付けたら旨いんじゃないか」という、地平線上に漂う黒い雲のような「これは来るんじゃないか」という予感がしてきました(なんちゅう喩えか)。すなわち鯛の頭購入。それからアメリカ産豚肩ロース塊が安かったので購入。これは焼き豚にしよう。魚と肉とでは明らかに子供のテンションが違うのです。料理を作る以上、喜んでもらいたい。というわけで豚塊肉。

これから材料の仕込みを始めます。よい休日になりそうな予感。

(夕方追記)
パン粉焼きにしようと思ったんですが、子供を迎えに行っていろいろ用事を済ますうちに疲れてきちゃったので、からあげに変更。美味かった。
でも子供には不評。箸もつけずに「不味い」「嫌い」とのたまう。いいから食べてみ。美味いから。「イヤ。食べたくない」。じゃあ食べないとオヤツなしにする、と脅して無理やり食べさせる。と、一口、二口。一切れ食べて、二切れ目、タルタルソースをたっぷりつけて美味しそうに食べ始めた。な、美味いだろ!と聞いてみると、タルタルソースが美味しい。タルタルソースが魚の味を消してくれる、とのこと。やれやれ。

不思議と腹が立たないのは、オレも昔母親の料理に文句つけてたなあ、という記憶がよみがえるからか・・・。子供は親の料理にケチをつけるもの。親は子供にケチをつけられても(食べてさえくれれば)腹は立たない。そんなものかも知れません(食べないと怒るけどね)。

私の母親も、子供に文句を言われて悲しかったのかな。親になってみるとそうは思えないんだな。とにかく子供が食べてくれさえすれば、文句は言われても気にならないもん。母親の本当の気持ちは分かりませんがそんな気がしました。たまに「美味しかった!」と言ってくれれば、それでいいんだ。不味いとか美味いとか言いながら家族で食べる、それだけで。

刺身用と思ったサンマ一本。これも取りやめ。むしろ酢締めが食べたい。疲れたらやっぱり酢っぱいものでしょ。で、大名おろしした後に塩をまぶしたはいいものの(酢で〆る前の手順です)、そのまま忘れて夕食完了(ありがち)。しょうがないので塩を水で流して水分をキッチンペーパーで拭き取り、冷凍しました。末は蒸しサンマか焼きサンマ?

鯛のおかしら(アラだけ)+大根は旨かった。これでダシを取っておでん作ったら旨いんじゃないかな。今度試してみよう。

焼き豚いい感じ。ちょっと焦がしてしまいましたが、味は悪くない。明日が楽しみです。

(2008/11/28追記)
冷凍したサンマは燻製にして美味しく頂きました。中華鍋で燻製。使えますよ。おっちゃんのママゴトかとおもったら十分実用的。ちょっとしたたんぱく質を軽く熱燻すれば、燻製風味の深い味に速変わり。簡単・美味しい・後片付けが楽。こんなお遊びみたいな調理法が定番化するとはね。
.

2008年11月21日金曜日

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(3)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
(前回はここまで)
5. JSFを作成
(今回はここまで)
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)

5. JSFを作成(参照のみ)

以下の3ページを作成します。
(1) mysampleのキー(myid)入力画面
(2) キーを持つレコードが存在した場合、それを表示するページ
(3) 存在しない場合に表示するページ

テスト環境(WAS v7サーバー)が起動していたら停止して下さい(私の環境ではハングすることがありました。重すぎるんでしょう)。

ファイル > 新規 > 新規動的 Web プロジェクトをクリックします。
ウィンドウが現れるので、プロジェクト名に MySampleJSF と入力し、EARメンバーシップに MySampleEar があることを確認して 終了 をクリックします。

例によってモジュールの依存関係を定義します。 MySampleJSFを右クリック > プロパティ > Java EE モジュール依存関係 でMySampleEJBClient.jarとMySampleJPA.jarにチェックを入れます。

JSF用のBeanを作成します。

MySampleJSF を右クリックし、新規作成 > クラス を選択します。
新規Javaクラス ウィンドウに

パッケージ:test.beans
名前:MySampleBean

と入力し「終了」をクリックします。

MySampleBean を以下のように作成します。
package test.beans;

import java.io.Serializable;

public class MySampleBean implements Serializable {

private static final long serialVersionUID = 1L;

int id;
String value;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}

/* まずはスタブを作成します */
public String checkInput() {
if (id == 0) {
return "success";
} else {
return "failure";
}
}
}

■web.xmlにFacesサーブレットを定義します。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>
MySampleJSF</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

■/WEB-INF/faces-config.xml を作成します。
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>
<managed-bean>
<managed-bean-name>mySampleBean</managed-bean-name>
<managed-bean-class>test.beans.MySampleBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/search.jsp</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/WEB-INF/results/success.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

次にJSPです。

■index.jsp
<% response.sendRedirect("search.faces"); %>

■search.jsp
<%@page language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>検索</title>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-31j">
</head>
<body>
<CENTER>
<h2>検索</h2>
<h:form>
myid:
<h:inputText value="#{mySampleBean.id}" />
<h:commandButton value="検索実行"
action="#{mySampleBean.checkInput}" />
</h:form>
</CENTER>
</body>
</html>
</f:view>

■/WEB-INF/results/success.jsp (パスに注意)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
OK
</body>
</html>

■/WEB-INF/results/failure.jsp
success.jspの"OK"を"NG"に変更するだけ。

これで動作確認をしてみましょう。"0"を入力すれば画面に"OK"が、"0"以外だと"NG"が表示されるはずです。

次にEJBと連携させます。

実はここまでくれば簡単です。

MySampleBean を以下のように変更します(太字部分)。
package test.beans;

import java.io.Serializable;

public class MySampleBean implements Serializable {

private static final long serialVersionUID = 1L;

int id;
String value;

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}

public String checkInput() {
MySample ms = mySampleSession.findMySample(id);
if (ms != null) {
this.setValue(ms.getMyFlag());
return "success";
} else {
return "failure";
}
}
}

次にsuccess.jspを変更します。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Found bean.<br>
id -> ${ mySampleBean.id }
value -> ${ mySampleBean.value }
</body>
</html>

以上。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(2)

今回の手順は以下のページほとんどそのままです。
Building Java EE applications with IBM Rational Application Developer V7.5 ... (IBM dWの記事)
が、若干違う+dWの手順では上手く行かないところがあるのでご注意ください。

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
(前回はここまで)
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
(今回はここまで)
5. JSFを作成(参照のみ)
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)

3. JPA/EJBを作成(findメソッドのみ)
一旦サーバーは止めましょう。重いし(私の環境ではハングすることもありました)。
(1)JPAプロジェクトを作成します。
ファイル > 新規 > その他 > JPAプロジェクト をクリックし 「新規 JPA プロジェクト」ウィンドウを起動します。以下の情報を入力します(MySampleEARは存在していません)
プロジェクト名:MySampleJPA
EARメンバーシップのEAR プロジェクト名:MySampleEAR
「終了」をクリックします。

(2)エンティティ(≒DBとマップされたBean)を作成します
「MySampleJPA」フォルダを右クリックし、新規作成 > エンティティー を選択します。
「新規 JPA エンティティー・エンティティークラス」ウィンドウで以下の情報を入力します。
Java パッケージ:test
クラス名:MySample
「次へ」をクリックします。
「新規 JPA エンティティー・エンティティープロパティ」のエンティティ・フィールドを埋めます。
追加をクリックしてエンティティーフィールドダイアログを表示
タイプ:int
名前:myid
としてOKをクリック。
「鍵」カラムにチェックを入れておきます。
再び「追加」をクリック。以下の情報を入力します。
タイプ:String 要注意!!タイプは char ではありません!!
名前:myFlag (敢えてテーブルのカラム名と異なるものを使っています)

「終了」をクリックすると以下のソースが生成されます。
package test;

import java.io.Serializable;
import javax.persistence.*;

/**
* Entity implementation class for Entity: MySample
*
*/
@Entity

public class MySample implements Serializable {


@Id
private int myid;
private char myFlag;
private static final long serialVersionUID = 1L;

public MySample() {
super();
}
public int getMyid() {
return this.myid;
}

public void setMyid(int myid) {
this.myid = myid;
}
public char getMyFlag() {
return this.myFlag;
}

public void setMyFlag(char myFlag) {
this.myFlag = myFlag;
}

}

アノテーションを追加します。(太字部分)
package test;

import java.io.Serializable;
import javax.persistence.*;

/**
* Entity implementation class for Entity: MySample
*
*/
@Entity
// ここでスキーマ名を指定します
@Table(schema="learning", name="mysample")
public class MySample implements Serializable {


@Id
private int myid;
// ここで変数名とは異なるカラム名を指定します。
@Column(name="mychar")
private char myFlag;
private static final long serialVersionUID = 1L;

public MySample() {
super();
}
public int getMyid() {
return this.myid;
}

public void setMyid(int myid) {
this.myid = myid;
}
public char getMyFlag() {
return this.myFlag;
}

public void setMyFlag(char myFlag) {
this.myFlag = myFlag;
}

}

次にJPAのpersistent.xmlにデータソース名指定します。
「MySampleJPA」フォルダ > 「JPAコンテンツ」 > persistence.xml をクリックします。
左ペインの「パーシスタンス・ユニット」を選択し、右側のペインのJTAデータ・ソースに 2.(3)で指定した jdbc/learning を入力します。

以上でJPAの作成が完了です。(残念ながらここでは動作検証は出来ません)

次にEJBプロジェクトを作成します。

ファイル > 新規 > EJBプロジェクト を選択して「新規 EJB プロジェクト・EJB プロジェクト」ウィンドウを起動します。
プロジェクト名に MySampleEJB と入力します。EJBモジュールバージョンが3.0であること、EARメンバーシップのEARプロジェクト名が MySampleEAR であることを確認し、「終了」をクリックします。

MySampleEJBフォルダを右クリックし プロパティ > Java EE モジュール依存関係 をクリックします。「選択可能な従属JAR」で「MySampleJPA.jar」にチェックを入れ、OKをクリックします。

MySampleEJB > MySampleEJB > セッションBean を右クリックします。コンテキストメニューから 新規 > セッションBean を選択します。

「EJB 3.0 セッションBean の作成ウィンドウ」に以下の情報を入力し、「ビジネス・インターフェースの作成」が「ローカル」になっていることを確認して終了をクリックします。
Javaパッケージ:test
クラス名:MySampleSession

生成されたEJBソースに下記の太字部分を追記します。
package test;

import javax.ejb.Stateless;

/**
* Session Bean implementation class MySampleSession
*/
@Stateless
public class MySampleSession implements MySampleSessionLocal {

/**
* Default constructor.
*/
public MySampleSession() {
// TODO Auto-generated constructor stub
}

@PersistenceContext(unitName="MySampleJPA")
EntityManager em;

public MySample findMySample(int myid) {
MySample ret = (MySample)em.find(MySample.class, myid);
return ret;
}

}

次にメソッドをプロモートします。

(重要 dWの記事には欠けていますが、以下の手順が必要です)
MySampleEJBClientフォルダを右クリックして、コンテキストメニューからプロパティを選択、次にJava EE モジュール依存関係 をクリックして「選択可能な従属JAR」で「MySampleJPA.jar」にチェックを入れます。

次に「アウトライン」ビューでfindMySampleを右クリック、コンテキストメニューから「Java EEツール」>「メソッドのプロモート」を実行します。

以上でEJBの作成が完了しました。

ここでユニバーサルクライアントを利用して動作確認をしてみます。

RADのサーバービューでWASサーバを起動します。

サーバーを右クリックし プロジェクトの追加および除去 を選択、MySampleEARを追加します。

公開が完了し、同期済みステータスになったら、サーバーを右クリックし、Universal Test Client > 実行 をクリックします。UTCが起動するのでログインします。(プロジェクトの追加以前にUTCを起動したことがあれば、一度「再起動」をクリックしてください)

「JNDIエクスプローラー」リンクをクリックします。

test.MySampleSessionLocalが表示されるのでクリックします。
※ そもそも表示されない場合はどこかで手順を間違っている可能性があります。プロジェクトがサーバに追加(デプロイ)されているかどうか等、手順を確認して下さい。
※ リンクではなく単にテキストが表示されている場合は、UTCの再起動を試して下さい。それでも出来ない場合はやはり手順を見直して下さい。

左側のペインに
MySampleSessionLocal
- MySampleSessionLocal
- メソッドの可視性
- MySample findMySample(int)
と表示されます。MySample findMySample(int) をクリックして下さい。

右側のペインに
test.MySample findMySample(int)

パラメーター 値
int: 0

と表示されています。そのまま「起動」をクリックします。

test.EJSLocal0SLMySampleSession_af305597.findMySample()
test.MySample@1ee01ee0 (test.MySample)

などと表示されれば成功です。「オブジェクトの使用」> String getMyFlag() ('a'が返る)などで遊んでみてください。

以上でEJBの作成が完了です。(しかしEJB簡単になったなあ)

RAD内のサーバーを止めてから、次のステップに行きます。

.

Rational Application Developer(以下RAD) v7.5 試用版 でJSFとEJB3.0を使ってCRUDアプリ作成(1)

試用版のダウンロード先です。IBM IDが必要です。(誰でも作成できると思います。)ダウンロードには丸一日かかります。

DBはMySQL v5.0を使いました。

IBM dWのBuilding Java EE applications with IBM Rational Application Developer V7.5 and WebSphere Application Server V7.0をベースに発展させて行きます。

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
(初回はここまで)
3. JPA/EJBを作成(findメソッドのみ)
4. JSFを作成(参照のみ)
5. EJBに挿入メソッドを作成する
6. JSFを作成(挿入)
7. EJBに更新メソッドを作成する
8. JSFを作成(更新)

1. サンプルDBを作成
create database learning;
use learning; -- このコマンドはMySQL独自。
drop table mysample;
create table mysample(
myid integer primary key,
mychar char(1)
);

delete from mysample;
insert into mysample values(0,'a');
insert into mysample values(1,'b');
insert into mysample values(2,'c');

2. WAS v7のデータソースに登録
RAD上にまだWAS v7 サーバが存在しない場合は作成して下さい。サーバービューを右クリックして「新規作成」を選択してテキトーに入力すれば出来ると思います。
WASを起動します。(重い・・・)
起動が完了したらServer view の サーバーを右クリックして「管理」>「管理コンソール」をクリック。
管理コンソールにログインします。

(1)JDBCを登録
メインメニュー Resources > JDBC > JDBC Providers > New >
ウィザード形式で入力を求められます。以下の情報を入力。
Database type -> User-defined
Implementation class name -> com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
Name -> MySQL JDBC Driver
次のページで
ClassPath: c:/path/to/mysql-connector-java-5.1.6-bin.jar
以上。

(2)認証情報を登録
メインメニュー Security > Global security > Authenticationエリアにある Java Authentication and Authorization Service を展開 > J2C authentication data > New
ここで
Alias -> MySQL_Learning
Userid, password -> DBに接続するときのID、パスワード
と入力する。

(3)データソースを作成
メインメニュー Resources > JDBC > Data source
Scope : 適切なスコープを設定(分からなければ'...Server = server1'とあるものを選びます)
> New
ウィザード形式で入力を求められるので下記情報を適宜入力します。
Data source name -> MySQL_Learning
JNDI name -> jdbc/learning(JPAに教えるので覚えておくこと)
> Next
Select an existing JDBC provider で MySQL JDBC Driver を選択
> Next
(何もしない)
> Next
Component-managed authentication alias
で、先ほど作成した認証情報(ノード名/MySQL_Learning)を選択。(JPAから参照するため、その他のaliasは不要。多分ServletからID/Passwordなしで利用するときはContainer-managed...が必要。Mapping-configurationは何か知らない・・・)
> Next
内容を確認
> Finish

次にカスタムプロパティを設定します。
JDBC providers > MySQL JDBC Driver > Data sources > MySQL_Learning > Connection pools > Custom properties > New
以下の情報を入力します。
Name -> url
Value -> jdbc:mysql://localhost:3306/learning
テスト接続。Warningが出ますが無視して問題ありません。
(注意:カスタムプロパティを設定しなくてもテスト接続は成功する。でもこのプロパティを定義しておかないと実際には使えない。認証情報をContainer-managedのみにしても成功するが、JPAからは使えない。すなわちテスト接続が成功しても油断しないで下さい)

まずは以上です。
.

2008年11月20日木曜日

SQL私観

はい。負け犬の遠吠えです。

SQL。難しすぎです。

もちろん単体のテーブルをSelectしたり、2,3個のテーブルをJOINする分には難しいことなどなにもありません。しかし、ちょっと細かい選択をSQLで作りこもうとすると、大変です。まるでクイズ。つーか実際SQLで課題を解くクイズが、実際にありますよね(しかもかなりたくさん)。今仕事してんだよ。クイズ解いてる暇ねーんだよ。とちょっと野蛮な言葉遣いになってしまいましたが、SQLのクイズとか見ていると何でこんなに難しいんだ、と思います。つーかクイズが成り立つ言語ってどうよ?

難しい理由は何か。それはSQLだから。つまりSQLだから難しい。すなわち難しさはSQLの本質的な属性と言えましょう。(この辺、論理大丈夫かな)

あまりにも難しいがために、便宜的で安直な解釈/用法がまかり通り、今ではそれがほとんど常識となっています。つまりデータを正規化してテーブルに落とし、キーでJOINして、SELECTしてINSERTして・・・。実際には非常に複雑で非直感的な仕組みの上に成り立っているのですが、それをばっちり隠蔽してしまっている。

いや、結果的にそうならざるを得ないと思いますし、それが正しいと思うんですよ。正面からSQLを理解するのってもはや研究者の仕事としか思えません。

初心者が何となくJOINを使って実装してしまうと(何となく実装するな、というツッコミを貰いそうですが、そうならざるを得ないプロジェクトがいかに多いことか)、内部の動きが隠蔽されている分、やってみなければパフォーマンスに問題がないか分からない。いや、やってみても分からない。十分にデータを突っ込んで試さない限りは。すなわちパフォーマンスチューニングが非常に難しい(統計情報に依存/実行計画の確認が必要)のがSQLです。初心者がSQLを作りこめばそこにパフォーマンスのリスクが生じる。脅しや極論ではなく、プロジェクトを運営する人が身に染みている分かっていることだと思います。

Java、Cなどの言語に毒された発想かもしれませんが、少なくとも処理が逐次的に理解できる手続き的な解法の方が、パフォーマンスへの影響を見極めやすいなど、メリットが多いと思えます。しかし複雑なSQLで解こうとすると、実行計画を実際に見ない限りどうなっているのか分からないし、しかもそれも統計情報に依存するわけで。

初心者はJOIN原則禁止。副照会厳禁。別に恥じることはないですよ。これでいいんじゃないか、と私は思います。え?それじゃ学習しないって?やっぱりダメか。

以上
.

ダイエットその後

ダイエット順調ですね。うむ。胃が軽くなって来た感じがあります。体重もゆるゆると落ちてきました。

酒は一日2~3合あたりで安定してます。最近は飲み過ぎてないです。食事中にワイン1合。食後にチーズなど軽くつまみながらウィスキー60~100ml。なんだか物足りないな、という日は寝る前にウィスキーか焼酎を少々(~60ml)。休日はいつも飲み過ぎてしまうんですが(夕方から一杯やり始めてだらだらと止めどなく飲む)先週末は3合未満で押さえました。素晴らしい!!よくやった!!

私の場合「食べる→飲む」という流れが強いようです。「飲む→食べる」というベクトルはさほど強くない。また、「飲む→飲む」という展開にはなりにくい。すなわち「飲む」の後に「食べる」をかまさなければ、だらだら飲み続けるということがなくなるようです。なんか食べたいなあ、でも我慢しなきゃ、などと思いつつ昔買ったDancyu(グルメ雑誌)や料理本など眺めながら、今度は何を食べてやろう、とチビチビ酒をすするのが至福の時です(しかし食欲強いな)。

さあこの調子で頑張ろう。
.

2008年11月17日月曜日

SQLについて分かったこと

「以降でSQLの勉強結果をブログに書込みたい」と書きました。はい。何が分かったか。自分が分かっていなかったことが分かりました。SQLが難しいということがよく分かった。そういうことです(泣)。

SQLの基本はデカルト積で得られた集合ってことですね。
正規化だとか「表」だとかプライマリキーとか、そういう話は一度忘れてしまうこと。手続き型の解法も忘れてしまえ。

以下、JOINの振る舞いについて記載します。(MySQLとDB2の方言をただ並べただけかも・・・)

準備。
drop table hoge;
create table hoge(
col1 char(1),
colh_2 char(1)
);
drop table piyo;
create table piyo(
col1 char(1),
colp_2 char(1)
);

delete from hoge;
insert into hoge values('a','a');
insert into hoge values('b','b');
insert into hoge values('c','c');
insert into hoge values('X','x');
insert into hoge values('Y','y');
insert into hoge values('Z','z');
delete from piyo;
insert into piyo values('1','1');
insert into piyo values('2','2');
insert into piyo values('3','3');
insert into piyo values('X','X');
insert into piyo values('Y','Y');
insert into piyo values('Z','Z');

MySQLとDB2で試しました。JOINについては方言があることを確認(仕様としてどうなのか、までは踏み込んでいません。MySQLに癖がある気がします)。

(1) デカルト積-1
MySQL: select h.col1, h.colh_2, p.col1, p.colp_2 from hoge h, piyo p;
DB2: select h.col1, h.colh_2, p.col1, p.colp_2 from hoge h, piyo p;

(2) デカルト積-2
MySQL: select h.colh_2, p.colp_2 from hoge h, piyo p;
DB2: select h.colh_2, p.colp_2 from hoge h, piyo p;

(3) しつこくデカルト積-3
MySQL: select h.col1, p.col1 from hoge h, piyo p;
DB2: select h.col1, p.col1 from hoge h, piyo p;

要するに
from hoge, piyo

した時点で、裏に巨大な直積集合ができているわけです。

今度はjoinの振る舞いを確認
(4) JOIN単体
MySQL: select h.colh_2, p.colp_2 from hoge h join piyo p; (1)と同じ結果が得られる。
DB2: JOIN単体ではエラー
(select h.colh_2, p.colp_2 from hoge h, piyo pで同様の結果が得られる)

(5) 今度はクロス結合。
MySQL: select h.colh_2, p.colp_2 from hoge h cross join piyo p;
DB2: CROSS JOINはエラー(でもMySQLでも単に'cross'が無視されているだけかも?)

(6) INNER JOIN ON ~
MySQL: select h.colh_2, p.colp_2 from hoge h inner join piyo p;
DB2: select h.colh_2, p.colp_2 from hoge h inner join piyo p on h.col1 = p.col1;

結果に相違あり。MySQLでは直積集合がそのまま表示されている。(inner が無視されている?)
DB2では合致する行のみが表示される。↓
db2 => select h.colh_2, p.colp_2 from hoge h inner join piyo p on h.col1 = p.col1

COLH_2 COLP_2
------ ------
x X
y Y
z Z

3 レコードが選択されました。

同様の結果をMySQLで表示するためには、
mysql> select h.colh_2, p.colp_2 from hoge h inner join piyo p where h.col1 = p.col1;
+--------+--------+
| colh_2 | colp_2 |
+--------+--------+
| x | X |
| y | Y |
| z | Z |
+--------+--------+
3 rows in set (0.00 sec)

とする。

(7) LEFT JOIN
MySQL: select h.colh_2, p.colp_2 from hoge h natural left outer join piyo p;
DB2: select h.colh_2, p.colp_2 from hoge h left outer join piyo p on h.col1 = p.col1;

これはMySQLとDB2で結果が同じ。
+--------+--------+
| colh_2 | colp_2 |
+--------+--------+
| a | NULL |(DB2では'-'ハイフンが表示される)
| b | NULL |
| c | NULL |
| x | X |
| y | Y |
| z | Z |
+--------+--------+
6 rows in set (0.00 sec)

(8) RIGHT JOIN
MySQL: select h.colh_2, p.colp_2 from hoge h natural right outer join piyo p;
DB2: select h.colh_2, p.colp_2 from hoge h right outer join piyo p on h.col1 = p.col1;
(DB2での実行例)
db2 => select h.colh_2, p.colp_2 from hoge h right outer join piyo p on h.col1 = p.col1;

COLH_2 COLP_2
------ ------
- 1
- 2
- 3
x X
y Y
z Z

6 レコードが選択されました。

これもLEFT JOIN同様両者の結果は変わらず。

(9) FULL OUTER JOIN
MySQL: full outer join 未対応
DB2: select h.colh_2, p.colp_2 from hoge h full outer join piyo p on h.col1 = p.col1;
db2 => select h.colh_2, p.colp_2 from hoge h full outer join piyo p on h.col1 = p.col1;

COLH_2 COLP_2
------ ------
- 1
- 2
- 3
x X
y Y
z Z
a -
b -
c -

9 レコードが選択されました。

同様の結果をMySQLで出すためには
mysql> select h.colh_2, p.colp_2 from hoge h natural right outer join piyo p
-> union
-> select h.colh_2, p.colp_2 from hoge h natural left outer join piyo p
-> ;
+--------+--------+
| colh_2 | colp_2 |
+--------+--------+
| NULL | 1 |
| NULL | 2 |
| NULL | 3 |
| x | X |
| y | Y |
| z | Z |
| a | NULL |
| b | NULL |
| c | NULL |
+--------+--------+
9 rows in set (0.00 sec)

まあ美しくはありません。

なんだか支離滅裂なようですが、SQLが難しいってことがよく分かりましたよ。あたしゃ。

もうこれから原則JOIN禁止。副照会はいかなる理由があっても厳禁。

以上。
.

2008年11月16日日曜日

節酒は楽しい

今回は、わりと節酒は楽しいというトーンで。

節酒もいいですね。目標は一日二合まで。それが私の節酒です。

日本酒一合が、大体ワイン一合ですね。他は、≒ビール(発泡酒・チューハイ)500ml ≒ウィスキー60ml ってとこです。

つまり二合を日本酒、ワイン、ビール類、ウィスキーで消費するわけで。となると、組み合わせは4x4の16通り。日本酒一合にワイン一合とか、ウィスキーとワインとか、日本酒二合とか。いやいや、例えばビール(発泡酒・チューハイ)を350mlにすれば、残りの150ml分を別の酒に割り当てられるわけで。結構選択肢はあるわけで。

それはともかく、呑む量を制限するとそこに投資の余地が出てくることは確かです。

今まではいかに安く、効率的に酔うか、が課題でした。

すなわち、ワインは500円前後のもの。焼酎は甲類と乙類の間を彷徨い(分かんない人、分かんなくていいです)、ウィスキーはブラックニッカ決め打ち。ビールは小遣い日のみ。普段は発泡酒未満。とにかく安くて量があればいい。そんな価値観です。

ところが、一日二合となるとその発想は通用しない。せっかくの二合ですから、できればおいしく頂きたい。かといって予算には上限がある。すなわち少し上を目指しつつ、あまり高くないものを探すことになる。

すると、いわゆる「安くて美味い」というエリアが広がってくるんですね。特にワイン、ウィスキー、日本酒、焼酎。(要するにビール・チューハイ以外ですな)

ワインについて言えば、1,000円前後/720mlなら躊躇せず買えるレベルになる。この価格帯だと、結構(500円未満に慣れた舌を)うならせるものが出てくるんです。ウィスキーも1,000円前後/720mlを許容すると、普通の輸入スコッチ(カティサーク、ジョニ赤)、バーボン(ジャックダニエル白、緑(好き)、フォア・ローゼズなど)も選択肢に入ってくる。焼酎も雲海(蕎麦)とか黒霧島(芋)あたりが射程範囲。日本酒も、米100%だけど純米酒じゃない酒(分かんない人、分かんなくていいです)、あるいはとっても薄い本醸造、一升1,000円前後から脱出して「美味い本醸造酒」「安いけどまっとうな純米酒」が選択肢に入ってくる。

心置きなく泥酔するという選択肢を捨てるのは残念ではありますが(残念だけど、死ぬまで泥酔し続けるわけにもいかんし)、それに変わっておいしくお酒をたしなむというのも、まあ、悪くないかな、という気がしないでもない今日この頃であります。

以上。
.

2008年11月14日金曜日

Open JPAを試す(2)

付属のサンプルをAntに依存しない Eclipse プロジェクトに移行する方法については、簡単ですが前に書いた通りです。

次はPersistentオブジェクト(正式には何というのか。要するにテーブルを表現したBeanです)を作成してみます。

手順は簡単でした。

(1) Message をコピーして MyMessage を作成(クラス名以外は何もせず)

(2) Main.javaに以下を追加
        q = em2.createQuery("select mm from MyMessage mm");
for (MyMessage mm : (List<MyMessage>) q.getResultList()) {
System.out.println(mm.getMessage()
+ " (created on: " + mm.getCreated() + ")");
}

(3)persistence.xmlに以下(太字部分)を追加
  <persistence-unit name="none" transaction-type="RESOURCE_LOCAL">
<class>hellojpa.Message</class>
<class>hellojpa.MyMessage</class>
</persistence-unit>
<persistence-unit name="hellojpa" transaction-type="RESOURCE_LOCAL">
<class>hellojpa.Message</class>
<class>hellojpa.MyMessage</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost/pms" />
(中略)
</persistence-unit>

以上です。悪くないですね。

Annotation記法にさえ気をつければ、Hibernateよりは簡単な気がしますね。
でも、Hibernateから移行するか?しないと思うな。
これから初めてこの手のテクノロジーに手をつけるのなら、JPAで決定でしょうけどね。何たって標準技術だし。なんつって大したことやってないのにさかしらに語るのも下品ですな。

実はこの勉強に着手してすぐに、SQLについてちょっと腰を据えて勉強し始めてしまいました。と言っても初級レベルで恥ずかしいんですけど。実は今までちゃんと理解してなかったんです。できれば以降でSQLの勉強結果をブログに書込みたいと思っています。

以上
.

2008年11月13日木曜日

酒は一日2合まで!

diet関連投稿はもはや個人的な独白になってます。喉元過ぎれば熱さを忘れる。気をつけよう。

「酒 適性量」などでだらだらWebを眺めていると、2合以上飲むと脳が萎縮する可能性があるというような記述を見つけました。お~怖~。

科学的な根拠ならびに真偽はさておいて(それなりに確度は高そうですが)、知ってしまった以上は節酒に励むしかないですよね。

今まではいかに安く効率よく酔えるか、という観点で酒を買っていたのですが、今後はいかに安く2合以内で楽しめるか、という観点で酒を買うことになりそうです。

もちろんダイエットにも効果的なはず。

以上。頑張るぞ。
.

金と情報

『トヨタ奥田氏「厚労省たたきは異常。マスコミに報復も」』とのことです(http://www.asahi.com/national/update/1112/TKY200811120346.html)。

たまにこういう有力者がアケスケに言うのもいいかもしれませんね。

確かに最近のマスコミのバッシングは、その対象が何であれ、細かい、(モノによっては)くだらない、ショボイ、痛々しい、ということで見ていて情けないものはあります。その点では奥田氏に同意。

しかし、金を引き上げるぞ、という脅しもまた強烈だと思います。公表されている情報が既に直接的/間接的に金に影響されており、従って金を出した人間の都合のよいように選別されている、というのは暗黙の了解ではありますが、普段(特にasahi.comのトップページなどに)表立って出てくることはありません。

公表される情報は、絶対に金によってフィルタが掛かっている。それは間違いない。でもマスコミとしては絶対に認めたくない、認められないところだと思います(実際、是々非々でたくましく権力に立ち向かうマスコミ人もいるはず)。

まあしかし、こんな風にアケスケに公表されたことで、実は情報を握っているのはトヨタなど金を持ったスポンサーであり、そのスポンサーとくっついた広告代理店であることに、改めて気が付かされることは、たまには悪くないですね。冷静に情報を見るためには必須の前提知識でしょう。

以上
.

2008年11月12日水曜日

いかに腹を空かせないか

ダイエットの話です。

空腹は最高の調味料。空腹時に美味い飯を食べると、もはや止めること能わず。頭真っ白となってひたすら胃に詰め込むハメになってしまいます。

ということでいかに食事前に空腹にしないか、が重要。

じゃあおやつを食べればいいんじゃないか、ということになりますが、この手は上手く行かないことは経験済みです。(もちろん私の経験なので普遍的ではありません)

上手くいかなかった理由1)
しばらく続けてるともたれる。胃が疲れる。でイヤになる。

上手くいかなかった理由2)
食欲抑止効果に疑問。
油脂と炭水化物が多くなるせいか、肉類/野菜類には手が出る。

上手くいかなかった理由3)
「おやつの時間にとりあえず食べる」習慣が出来てしまい、空腹でなくても食べてしまう。

という訳で、今有効ではないか、と思っているのは甘いコーヒーや紅茶をちまちま啜る、という手です。これだと胃はあまり疲れないし、カロリーを取りすぎることがない。肉類/野菜類の抑止には効果はありませんが、おやつを食べるよりおはマシだと思っています。

以上
.