忍者ブログ
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

DATE : 2017/03/25 (Sat)
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


DATE : 2006/11/18 (Sat)

Hibernate 3.1 までは、データの件数を取得する処理は次のように書けました。(以下は、Cat クラスの全オブジェクトの件数を取得する処理です。)

int catCount = (Integer) session.iterate(
    "select count(*) from Cat").next();

しかし、Hibernate 3.2 からは、HQL の count 関数は Long 型を返すようになりました。つまり、以下のように書き直さなければなりません。

long catCount = (Long) session.iterate(
    "select count(*) from Cat").next();

この変更は、Java Persistence API に準拠するために行われたようです。そのため、Hibernate 3.2 以降で結果を Integer で取得しようとすると ClassCastException が発生します。

ただし、org.hibernate.cfg.Configuration を次のように設定すると、3.2 以降でも Integer で取り出すことができます。

configuration.addSqlFunction("count", new ClassicCountFunction()); 

なお、count 関数以外にも、sum や avg なども戻り値が変更されています。sum は、元々は合計された型そのものが返されていましたが、

  • Long 以下の整数型であれば Long
  • 浮動小数点数であれば Double
  • BigInteger や BigDecimal であればその型

と変わりました。また、avg は フィールドの型に依存していたものが、Double が返されるように変わりました。

sum や avg も含めて 3.1 以前の書き方を適用する場合は、次のように Configuration を設定します。

configuration.addSqlFunction("count", new ClassicCountFunction());
configuration.addSqlFunction("avg", new ClassicAvgFunction());
configuration.addSqlFunction("sum", new ClassicSumFunction());

ちなみに今のところ、Hibernate 3.2.0ga のドキュメント3.1以前の方法で書かれているので注意が必要です。

(;^ω^)見事にひっかかりました

参考文献

PR

DATE : 2006/11/16 (Thu)

処理の中で System.out.println などの標準出力への出力を行うメソッドをテストすると、テスト中に出力がコンソールに次々と流れ、テスト結果が埋もれてしまうことがあります。

そこで、標準出力を他の出力ストリームに割り当て直します。

割り当て直すには、java.lang.System#setOut(java.io.PrintStream) を使います。java.io.PrintStream はコンストラクタの一部に java.io.OutputStream をとるものがあります。そこで、OutputStream として java.io.ByteArrayOutputStream を割り当てます。ByteArrayOutputStream は、ストリームに書き込まれたバイト列を byte 配列に書き込む出力ストリームです。他の出力ストリームと比べて手頃なので、このストリームを選択しました。

ByteArrayOutputStream を標準出力に割り当てるコードは次のようになります。

System.setOut(new PrintStream(new ByteArrayOutputStream()));

このコードを、 JUnit の場合は setUp メソッド(もしくは @Before アノテーションの着いたメソッド)に記述すれば、そのテストクラスでの標準出力への出力を抑制することができます。

また、ByteArrayOutputStream オブジェクトを保持しておけば、ByteArrayOutputStream#toString() で出力された文字列を取り出すこともできます。標準出力に出力する文字列もテストする場合は、ByteArrayOutputStream オブジェクトを保持しておくと良いでしょう。

なお、標準エラー出力の場合も同様です。

System.setErr(new PrintStream(new ByteArrayOutputStream()));

DATE : 2006/11/15 (Wed)

java.lang.String#getBytes(String) メソッドを使うと、文字列を特定のエンコーディングに変換することができます。例えば、文字列 string を UTF-8 に変換するコードは次のようになります。

byte[] utf8 = string.getBytes("UTF8");

それに対して、java.nio.Charset などの New I/O を用いて文字列 string を UTF-8 に変換する場合は、次のようになります(ここでは、java.nio.Charset を使用した場合を示します)。

ByteBuffer utf8 = Charset.forName("UTF-8").encode(string);

byte 配列ではなく java.nio.ByteBuffer として返されるので、New I/O を使う際にはこちらを使った方が見通しが良くなります。

ただし、その結果返された ByteBuffer を操作する際には注意が必要です。

ByteBuffer は固定長のバイト列を表すオブジェクトで、バイト長を表す要素として「容量」と「リミット」があります。前者は ByteBuffer そのものの長さ、後者はバッファの読み書きを禁止し始める位置を表します。また、容量は ByteBuffer#capacity() で、リミットは ByteBuffer#limit() で取り出すことができます。

ここで、Charset#encode(String) で変換されたバイト長を表すのはリミットです。Charset#encode(String) で生成された ByteBuffer なので一見すると容量イコール変換されたバイト長のように思えます。しかし、変換されたバイト列を調べてみると、リミット以降はただ単に0が格納されていました。


DATE : 2006/11/12 (Sun)

Java Persistence API(JPA)を使用すると、Java Beans とデータベースとを比較的容易に対応付けることができます。

例えば、あるクラスの code プロパティを主キーとして対応付ける場合は、次のようになります(この場合、対応付けられるのはデータベースの code 列になります)。(「...」は省略を表します)

@Id
@Column
public Integer getId() {
    ...
}

public void setId(Integer id) {
    ...
}

また、主キーの値がデータベースによって自動生成される場合は、次のように指定します。

@Id
@Column
@GeneratedValue
public Integer getId() {
    ...
}
...

この GeneratedValue アノテーションには strategy という要素があります。この要素によって、主キーの値の生成方式を指定できます。

現在の Java Persistence API では、以下の方式が定義されています。

GenerationType.IDENTITY
データベースが識別番号を生成します。データベースやフレームワークが IDENTITY 型を定義している必要があります。
GenerationType.SEQUENCE
データベースが連番を生成します。データベースやフレームワークが連番型を定義している必要があります。
GenerationType.TABLE
連番の状態を特定のテーブルに保存することで、識別番号を生成します。
GenerationType.AUTO
Java Persistence API を提供するライブラリやフレームワークが、自動的に方式を判断します。

PostgreSQL では、連番型を表す serial 型が定義されています。そのため、serial 型の主キーにプロパティを対応付ける場合、Generation.SEQUENCE を指定しがちです。

@Id
@Column
@GeneratedValue(stragegy = GenerationValue.SEQUENCE)
public Integer getId() {
    ....
}

しかし実際には、Generation.IDENTITY を指定しなければ正しく動作しません

@Id
@Column
@GeneratedValue(stragegy = GenerationValue.IDENTITY)
public Integer getId() {
    ...
}

なぜ SEQUENCE ではなく IDENTITY なのかは、勉強不足のため正確なところはわかりません。

ただ、PostgreSQL の連番型は、連番を生成するジェネレータから出力される値が連番であるだけで、主キー列が必ずしも連番になるとは限りません(例えば、トランザクションがアボートされた場合、ジェネレータの連番は元に戻りません。つまり、主キーの連番が1つ空くことになります)。

このあたりが、PostgreSQL の連番型には SEQUENCE ではなく IDENTITY を指定する理由なのではないかと思います。

参考文献


DATE : 2006/11/10 (Fri)

JSF には、ユーザが入力フィールドなどに入力した内容を検証できる Validator があります。例えば、javax.faces.validator.LengthValidator は、入力された文字数が一定の範囲内にあるか検証できますし、org.apache.myfaces.custom.emailvalidator.EmailValidator は入力された文字列がメールアドレスの形式になっているか否かを検証できます。また、javax.faces.validator.Validator インタフェースを実装することで、自分なりの Validator を作ることもできます(他にも、検証を行うメソッドを直接記述する Validator もあります)。

インタフェースを実装した Validator は、JSF の設定ファイルである faces-config.xml に登録すると使えるようになります。例えば、以下は project.jsf.MyValidator を myValidator として登録した部分です。

<validator>
    <validator-id>myValidator</validator-id>
    <validator-class>project.jsf.MyValidator</validator-class>
</validator>

こうして登録した Validator を入力フィールドで使用するには、次のようにします。以下は、入力フィールドに入力された文字列を myValidator が検証し、合格であれば myBean の value プロパティに文字列を設定する部分です。不合格の場合は、入力フィールドに続いてエラーメッセージが表示されます(h:message タグの部分になります)。

<h:inputText id ="textField" value="#{myBean.value}">
    <f:validator validatorId="myValidator" />
 </h:inputText>
<h:message for="textField" />

しかし、Validator の使用には注意が必要です。入力フィールドが空値の場合、Validator は実行されません。つまり、空値の場合は空値がそのまま myBean の value プロパティに設定されてしまいます。

実は、入力フィールドなどの入力を求める部分に文字列があるかを検証する方法は、別に用意されています。

それは required 属性で、この属性を true に設定すると、入力を必須にすることができます。

上の例では、次のようになります。

<h:inputText id ="textField" value="#{myBean.value}"
        required="true">
    <f:validator validatorId="myValidator" />
 </h:inputText>
<h:message for="textField" />

Validator 同様、h:message タグの部分にエラーメッセージが表示されます。

すると、Validator では空値を検証する必要がないとも言えます。

(;^ω^)これにはそうとう長期間苦しめられました

参考文献

忍者ブログ [PR]
ブログ内検索
最近の状況
リンク
カレンダー
02 2017/03 04
S M T W T F S
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
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック
T/O
(11/05)
ブログ内検索
最近の状況
リンク
カレンダー
02 2017/03 04
S M T W T F S
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
使用許諾
最新コメント
(08/15)
(05/04)
(03/06)
(03/04)
(09/25)
最新トラックバック
T/O
(11/05)