h:selectOneMenuのオプションをデータベースから入力する方法は?
質問
DBからオブジェクト/エンティティのリストを読み込んで、JSFに入力する必要があるWebアプリケーションを作成しています。
<h:selectOneMenu>
. 私はこれをコード化することができません。誰かがそれを行う方法を私に示すことができますか?
私はどのように
List<User>
をDBから取得する方法は知っています。私が知る必要があるのは、このリストを
<h:selectOneMenu>
.
<h:selectOneMenu value="#{bean.name}">
...?
</h:selectOneMenu>
どのように解決するのですか?
質問履歴からすると、JSF2.xをお使いのようですので、JSF2.xをターゲットにした回答です。JSF 1.xでは、項目の値/ラベルを醜くラップすることを余儀なくされるでしょう。
SelectItem
インスタンスで包まざるを得ませんでした。これは幸いなことに、JSF 2.xではもう必要ありません。
基本的な例
質問に直接答えるには、単に
<f:selectItems>
その
value
を指し、その
List<T>
プロパティを指し、これはビーンの (後) 構築時に DB から保存します。以下は、基本的なキックオフの例で、以下を仮定しています。
T
が実際に
String
.
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{bean.names}" />
</h:selectOneMenu>
で
@ManagedBean
@RequestScoped
public class Bean {
private String name;
private List<String> names;
@EJB
private NameService nameService;
@PostConstruct
public void init() {
names = nameService.list();
}
// ... (getters, setters, etc)
}
というように単純です。実は、この
T
's
toString()
は、ドロップダウン項目のラベルと値の両方を表すために使用されます。ですから、あなたが代わりに
List<String>
のような複雑なオブジェクトのリストを使って
List<SomeEntity>
のような複雑なオブジェクトのリストを使っていて、 クラスの
toString()
メソッドをオーバーライドしていない場合、次のように表示されます。
com.example.SomeEntity@hashcode
と表示されます。この問題を解決するには、次のセクションを参照してください。
のビーンも
<f:selectItems>
のビーンと同じビーンである必要はありません。
<h:selectOneMenu>
の値と同じビーンである必要はありません。これは、値が実際にはアプリケーション全体の定数であり、 アプリケーションの起動時に一度だけロードする必要がある場合に便利です。そして、それをアプリケーションスコープドビーンのプロパティにすることができます。
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{data.names}" />
</h:selectOneMenu>
利用可能なアイテムとしての複雑なオブジェクト
いつでも
T
のような複雑なオブジェクト (javabean) に関係します。
User
のような複雑なオブジェクトに関係します。
String
のプロパティは
name
を使用する場合、その後に
var
属性を使って反復変数を取得し、それを
itemValue
または
itemLabel
属性(もし
itemLabel
を省略した場合、ラベルは値と同じになる)。
例1.
<h:selectOneMenu value="#{bean.userName}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.name}" />
</h:selectOneMenu>
で
private String userName;
private List<User> users;
@EJB
private UserService userService;
@PostConstruct
public void init() {
users = userService.list();
}
// ... (getters, setters, etc)
を持つ場合、あるいは
Long
プロパティ
id
というように、項目の値として設定したいものを指定します。
例2:
<h:selectOneMenu value="#{bean.userId}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.id}" itemLabel="#{user.name}" />
</h:selectOneMenu>
で
private Long userId;
private List<User> users;
// ... (the same as in previous bean example)
複合オブジェクトを選択アイテムにする
に設定したいときは、いつでも
T
プロパティと同様にビーン内の
T
は
User
を表すのであれば、カスタム
Converter
の間を変換する
User
と一意な文字列表現 (これは
id
プロパティにすることができます)。注意すべきは
itemValue
は複合オブジェクトそのものを表し、まさに選択コンポーネントの
value
.
<h:selectOneMenu value="#{bean.user}" converter="#{userConverter}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>
で
private User user;
private List<User> users;
// ... (the same as in previous bean example)
と
@ManagedBean
@RequestScoped
public class UserConverter implements Converter {
@EJB
private UserService userService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return userService.find(Long.valueOf(submittedValue));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(String.format("%s is not a valid User ID", submittedValue)), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
if (modelValue == null) {
return "";
}
if (modelValue instanceof User) {
return String.valueOf(((User) modelValue).getId());
} else {
throw new ConverterException(new FacesMessage(String.format("%s is not a valid User", modelValue)), e);
}
}
}
(なお
Converter
を注入できるようにするために、少しハチャメチャになっています。
@EJB
を注入することができるようにするために、ちょっとハックしています。
@FacesConverter(forClass=User.class)
,
というアノテーションをつけるでしょうが、残念ながらそれは
@EJB
インジェクション
)
複雑なオブジェクトクラスには、必ず
equals()
と
hashCode()
を適切に実装した
を実装していなければ、JSFはレンダリング中にあらかじめ選択された項目を表示することに失敗し、あなたは投稿時に
バリデーションエラー。値が有効ではありません
.
public class User {
private Long id;
@Override
public boolean equals(Object other) {
return (other != null && getClass() == other.getClass() && id != null)
? id.equals(((User) other).id)
: (other == this);
}
@Override
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}
}
汎用コンバータで複雑なオブジェクトを扱う
この答えに向かう。 Java Genericsでエンティティのコンバータを実装する .
カスタムコンバータを使用しない複雑なオブジェクト
JSFユーティリティ・ライブラリ
オムニフェーズ
は特別なコンバータを提供し、複雑なオブジェクトを
<h:selectOneMenu>
のように、カスタムコンバータを作成する必要がありません。その
SelectItemsConverter
にある利用しやすい項目に基づいて変換を行います。
<f:selectItem(s)>
.
<h:selectOneMenu value="#{bean.user}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>
こちらもご覧ください。
関連
-
[解決済み] ...値に挿入する ( SELECT ... FROM ... )
-
[解決済み] ATTACHで開いたSQLiteデータベースファイルのテーブルを一覧表示するにはどうすればよいですか?
-
[解決済み] MySQLデータベースの名前を素早く変更する(スキーマ名を変更する)方法は?
-
[解決済み] JavaScriptの "require "とは何ですか?
-
[解決済み] mysqlのデータベースが存在するかどうかを確認する方法
-
[解決済み] データベース レコードを削除するかしないか
-
[解決済み] Postgresqlサーバーのpostgresという名前のデフォルトのデータベース
-
[解決済み] 過去の生天気データはどこにありますか?[終了しました]
-
[解決済み] 私はCouchDBでトランザクションとロックを行うことができますか?
-
pg_restore error: role XXX does not exist
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 外部キーを主キーにするのは問題ないですか?
-
[解決済み] 変更履歴/監査データベーステーブルの最適なデザインは?[クローズド]
-
[解決済み] データベースのインデックスはいくつあっても足りない?
-
[解決済み] 非リレーショナルデータベース設計【終了しました
-
[解決済み] なぜ、いつ、Liquibaseなのか?
-
[解決済み] SQL Developerで新しい接続を追加する際にOracle TNSの名前が表示されない
-
[解決済み] ファセット検索とは何ですか?
-
[解決済み] データベースにおけるカーディナリティとは?
-
[解決済み] SQLiteのテーブルから最後のオートインクリメントされたIDを取り出すには?
-
[解決済み] 73億行のマーケットデータ(読み出しに最適化)を格納する方法とは?