Home > Java

Java Archive

2way SQL の挙動がおかしい(気がする)@S2JDBC

S2JDBC の 2way SQL の挙動が気になったのでメモ。
というか 2way SQL のパラメータが Map のときの挙動。

チュートリアルのテストケースを利用して検証してみました。
2.4.35 を使用します。

まずサンプルの 2way SQL をコピーして変更。

■ META-INF/sql/examples/entity/Employee/selectWithDepartment2.sql

  1.  select e.*, d.name as department_name
  2.  from employee e left outer join department d on e.department_id = d.id
  3.  /*BEGIN*/
  4.  where
  5.   /*IF salaryMin != null*/
  6.      e.salary >= /*salaryMin*/1000
  7.   /*END*/
  8.   /*IF salaryMax != null*/
  9.      and e.salary <= /*salaryMax*/2000
  10.   /*END*/
  11.   – 追加ここから
  12.   /*IF departmentId != null*/
  13.      and e.department_id = /*departmentId*/1
  14.   /*END*/
  15.   – 追加ここまで
  16.  /*END*/
  17.  order by e.salary

■ テストケースその1
パラメータをすべて指定してみる。

  1.  public void testSqlFile() throws Exception {
  2.  
  3.          // DTO
  4.          SelectWithDepartmentDto dto = new SelectWithDepartmentDto();
  5.          dto.salaryMin = 1200;
  6.          dto.salaryMax = 1800;
  7.          dto.departmentId = 3;
  8.          List<EmployeeDto> results =
  9.              jdbcManager
  10.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, dto)
  11.                  .getResultList();
  12.          System.out.println("—DTO—————————");
  13.          for (EmployeeDto e : results) {
  14.              System.out
  15.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  16.          }
  17.          System.out.println("————————-DTO—–");
  18.  
  19.          // MAP
  20.          Map map = new HashMap();
  21.          map.put("salaryMin", 1200);
  22.          map.put("salaryMax", 1800);
  23.          map.put("departmentId", 3);
  24.  
  25.          List<EmployeeDto> results2 =
  26.              jdbcManager
  27.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, map)
  28.                  .getResultList();
  29.          System.out.println("—MAP—————————");
  30.          for (EmployeeDto e : results2) {
  31.              System.out
  32.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  33.          }
  34.          System.out.println("————————MAP——");
  35.  
  36.      }

同じ SQL が発行されます。当然結果も同じです。

■ テストケースその2
パラメータを2つにしてみた。

  1.  public void testSqlFile2() throws Exception {
  2.  
  3.          // DTO
  4.          SelectWithDepartmentDto dto = new SelectWithDepartmentDto();
  5.          dto.salaryMin = 1200;
  6.          dto.salaryMax = 1800;
  7.          List<EmployeeDto> results =
  8.              jdbcManager
  9.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, dto)
  10.                  .getResultList();
  11.          System.out.println("—DTO—————————");
  12.          for (EmployeeDto e : results) {
  13.              System.out
  14.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  15.          }
  16.          System.out.println("————————-DTO—–");
  17.  
  18.          // MAP
  19.          Map map = new HashMap();
  20.          map.put("salaryMin", 1200);
  21.          map.put("salaryMax", 1800);
  22.  
  23.          List<EmployeeDto> results2 =
  24.              jdbcManager
  25.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, map)
  26.                  .getResultList();
  27.          System.out.println("—MAP—————————");
  28.          for (EmployeeDto e : results2) {
  29.              System.out
  30.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  31.          }
  32.          System.out.println("————————MAP——");
  33.  
  34.      }

同じ SQL が発行され、結果も同じなのですが、Map の方では WARN が出力される。

WARN 2009-05-04 06:52:33,250 [main] 引数(departmentId)が見つかりません

以下のように Map に key を設定すれば回避できますが…(ーー;)

  1.  map.put("departmentId", null);

■ テストケースその3
パラメータを1つにしてみた。

  1.  public void testSqlFile3() throws Exception {
  2.  
  3.          // DTO
  4.          SelectWithDepartmentDto dto = new SelectWithDepartmentDto();
  5.          dto.salaryMin = 1200;
  6.          List<EmployeeDto> results =
  7.              jdbcManager
  8.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, dto)
  9.                  .getResultList();
  10.          System.out.println("—DTO—————————");
  11.          for (EmployeeDto e : results) {
  12.              System.out
  13.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  14.          }
  15.          System.out.println("————————-DTO—–");
  16.  
  17.          // MAP
  18.          Map map = new HashMap();
  19.          map.put("salaryMin", 1200);
  20.  
  21.          List<EmployeeDto> results2 =
  22.              jdbcManager
  23.                  .selectBySqlFile(EmployeeDto.class, SQL_FILE, map)
  24.                  .getResultList();
  25.          System.out.println("—MAP—————————");
  26.          for (EmployeeDto e : results2) {
  27.              System.out
  28.                  .println(e.name + " " + e.salary + " " + e.departmentName);
  29.          }
  30.          System.out.println("————————MAP——");
  31.  
  32.      }

Map のとき、発行される SQL が違が …(*゚ロ゚*)

  1.  select e.*, d.name as department_name
  2.  from employee e left outer join department d on e.department_id = d.id
  3.  where
  4.      e.salary >= 1200
  5.      and e.salary <= 1200
  6.      and e.department_id = 1200
  7.  order by e.salary

Map のサイズが1のときだけ…?

中途半端ですがコードを追いきれなかったので今日はココまでです!

BufferedReaderの終端判定とか

@IT:連載 基礎から学ぶサーブレット/JSP 第9回

古い記事なのですが、気になる箇所を見つけました。

訂正のお知らせ(2009年3月31日)
読者から上記のサンプルコード、「while (objBr.ready())」について貴重なご指摘をいただき、コードを差し替え、また編集部注を追記させて頂きました。
内容について正確を期せずに混乱を招いた点、読者の皆様におわび申し上げます。

なぜか最近修正されています。
BufferedReader#ready() による判定から BufferedReader#readLine() の判定に変更されたということなのでしょうけど、変更内容について言及されていないのため、なにが問題だったのかわからないのです。

調べてみたところ、ready() に気になる記述がありました。

次の read() が入力をブロックしないのが確実な場合は true、そうでない場合は false。false が返されても、次の読み込みが確実にブロックするというわけでない
BufferedReader (Java 2 Platform SE 5.0)

ものすごくわかりにくいのですが、”falseでも読み込み対象がなくなったとは限らないよ”ということなんだと思います。疑わしきは false。
つまり、ファイル終端まで読み込むための判定とは目的が違うということです。

まあ記事の修正と関係あるのかはわかりませんが、ファイルなどを全部読み込む目的で ready() は使わないほうがよさそうです。

■ 参考
2003年12月のアレ

Javaファイル関連メモ(Hishidama’s Java File Memo)

Eclipseの水平ルーラー

Eclipse のエディタに水平ルーラーをつけてみました。

どうやって実装するかイメージがなかったのですが、 COBOL Editor なるものに水平ルーラーが実装されていたので、それを参考にしました。

簡単にいうと、SWTのコンポーネントを置いているだけですが、フォントやら日本語など、スクラッチじゃできなかっただろうなーと思います。

で、COBOL Editor の中に気になる箇所を見つけた。

■ スニペット
水平ルーラーのマーク位置を設定するところ。

  1.  char[] ch = new char[] {document.getChar(i)};
  2.  byte[] by = new String(ch).getBytes();
  3.  column += by.length;

例えば、”ほげほげほ”というテキストの末尾にカーソルがある場合、全角は2文字分の幅を使うのでルーラーの目盛は10になるはずです。

上記はその実装なのですが、UTF-8では全角日本語は3バイトだったりするのでバイト基準では、ずれてしまう…と思うのですがどうなんでしょう。

現在のコントリビュータは日本の企業なので、気付いていないって事もなさそうなんですけど。

技術書:Seasar2によるスーパーアジャイルなWeb開発

Seasar2を使うかもしれないってことで購入。

中身を確認しないで Web から購入したのですが、この本を選んだ理由は以下のようなところです。

・ 比較的新しい
・ 著者がひがさん
・ “入門”などとついていない

が、正直残念な感じの Web 開発入門って内容でした。
要は普段 Java (や別の言語でも)を使って Web アプリの開発をしている人をターゲットにしているわけじゃないってことでしょう。どんな人をターゲットにしているのかわかりませんが。

ぶっちゃけ、Seasar2は Web に多くの資料が公開されているので本を買う必要なんてないのですよ。
分厚いリファレンスになってしまうと、そもそもの”さくさく感”ってものが失われてしまいますからね。

そんなことを高い授業料を払って学んだってことで。
いや、でも高すぎると思います。

Seasar2によるスーパーアジャイルなWeb開発 (WEB+DB PRESS plusシリーズ)
Seasar2によるスーパーアジャイルなWeb開発 (WEB+DB PRESS plusシリーズ)

Eclipseプラグイン開発:ハイパーリンクのスタイル指定

久しぶりに Eclipse のプラグイン開発の話を。

テキストエディタ内にハイパーリンクを作ったときのスタイルを指定する。

ハイパーリンクにカーソルをあわせたとき、「青字、下線付き」になることを期待しますよね。
ところがハイパーリンクは動くものの、「青字、下線付き」にならないという現象に遭遇。そして原因がわからずはまったのでメモ。

まず、「青字、下線付き」となることを期待する根拠は SourceViewerConfiguration の実装です。

  1.  public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) {
  2.      return new DefaultHyperlinkPresenter(new RGB(0, 0, 255));
  3.  }

このようになっています。そのため、特別 Override しない限り、プレゼンテーションにはこの DefaultHyperlinkPresenter を使うことになります。
この DefaultHyperlinkPresenter には以下のコメントがあります。

The default hyperlink presenter underlines the link and colors the line and the text with the given color.

つまり、「青字、下線付き」ですよね。
それなのに、どうにも反応がありませんでした。
それでどうしたかというと、DefaultHyperlinkPresenter#applyTextPresentation 辺りにブレークポイントを設定してフィールド等を調べてみました。

結果わかったことは、範囲(Region)がうまく設定されてないってことです。
IHyperlink の実装クラスで Region を返すのですが、この Region が正しい範囲を指定していなかったのです。

  1.  public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
  2.      // (略)
  3.  
  4.      // !! パラメータの region をそのまま渡しちゃってる !!
  5.      //     これはリンクを検出する前の範囲!
  6.      hyperLink = new HogeHyperLink(region);
  7.  
  8.      // (略)
  9.  }

IHyperlink の実装クラス(ここでは HogeHyperLink)に渡す範囲は検出時に計算したものじゃないとダメ(当たり前)。

  1.  public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
  2.      // (略)
  3.  
  4.      // 検出結果のリンク文字列に対応した範囲を渡す!
  5.      hyperLink = new HogeHyperLink(new Region(linkOffset, linkOffsetLength));
  6.  
  7.      // (略)
  8.  }

あとは HogeHyperLink#getHyperlinkRegion で渡されてきた Region をそのまま返せば OK です。

単純なミスなのですけど、はまったので残しておきます。
げふ。

Eclipse 3.4 プラグイン開発 徹底攻略 Eclipse 3.4 Ganymede対応
Eclipse 3.4 プラグイン開発 徹底攻略 Eclipse 3.4 Ganymede対応

ホーム > Java

Search
Feeds
Link
あわせて読みたいブログパーツ
Meta
AD








DMM.com 家電・日用品通販

Return to page top