はじめに
前回は、
今回は、
ConditionBean
ConditionBeanにおける結合とは?
まず、
では、
- 結合先テーブルのデータを取得すること
- 結合先テーブルの条件で結果を絞り込むこと
ConditionBeanにおける結合は、
例えば、
final MemberCB cb = new MemberCB();
// 親テーブルの会員ステータスを結合し、Select句に含める。
cb.setupSelect_MemberStatus();
select member.MEMBER_ID, ... , memberStatus.MEMBER_STATUS_CODE, ...
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
また、
final MemberCB cb = new MemberCB();
// 親テーブルの会員ステータスを結合し、
// 「'正'という文字で始まる会員ステータス名」という条件で絞り込む。
cb.query().queryMemberStatus().setMemberStatusName_PrefixSearch("正");
select member.MEMBER_ID, ...
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
where memberStatus.MEMBER_STATUS_NAME like '正%'
無論、
結合に関連する目的が2つ指定されたからといって、
final MemberCB cb = new MemberCB();
// 親テーブルの会員ステータスを結合し、Select句に含める。
cb.setupSelect_MemberStatus();
// 親テーブルの会員ステータスを結合し、
// 「'正'という文字で始まる会員ステータス名」という条件で絞り込む。
cb.query().queryMemberStatus().setMemberStatusName_PrefixSearch("正");
select member.MEMBER_ID, ..., memberStatus.MEMBER_STATUS_CODE, ...
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
where memberStatus.MEMBER_STATUS_NAME like '正%'
ConditionBeanでは、
実際の業務ロジックでは、
「呼び出し側プログラムが必ず何のテーブルを取得したいのか? (絞込み条件に関わらず)
結合先テーブルのデータを取得すること
まずは、
実は、
結合して親テーブルの取得
まずは、
cb.
/**
* 結合して会員ステータス(親テーブル)を取得する会員一覧を検索
*
* @throws Exception
*/
public void test_ConditionBean_SetupSelect_ForeignTable_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
for (Member member : memberList) {
final MemberStatus memberStatus = member.getMemberStatus();
assertNotNull(memberStatus);
}
}
会員Entityから会員ステータスEntityが取得できます。
もし、
また、
この例題の場合は、
結合してone-to-oneテーブルの取得
テーブル設計において、
表現の仕方は様々ですが、
そして、
/**
* 結合して会員セキュリティ情報(one-to-oneテーブル)を取得する会員一覧を検索
*
* @throws Exception
*/
public void test_ConditionBean_SetupSelect_ReferrerAsOneTable_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.setupSelect_MemberSecurityAsOne();
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
for (Member member : memberList) {
final MemberSecurity memberSecurityAsOne = member.getMemberSecurityAsOne();
log.debug("memberSecurityAsOne=" + memberSecurityAsOne);
assertNotNull(memberSecurityAsOne);
}
}
会員Entityから会員セキュリティ情報Entityが取得できます。
もし、
また、
この例題の場合は、
また、
実際には親テーブルではありませんが、
結合して親の親テーブルの取得
そして、
まずは、
/**
* 結合して会員退会情報と退会理由(親テーブル&親の親テーブル)を取得する会員一覧を検索
*
* @throws Exception
*/
public void test_ConditionBean_SetupSelect_ForeignTable_with_Foreign_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.setupSelect_MemberWithdrawalAsOne().withWithdrawalReason();
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
boolean existsOneOrMoreAtLeast = false;
for (Member member : memberList) {
final MemberWithdrawal memberWithdrawalAsOne = member.getMemberWithdrawalAsOne();
log.debug("memberWithdrawalAsOne=" + memberWithdrawalAsOne);
if (memberWithdrawalAsOne != null) {
existsOneOrMoreAtLeast = true;
final WithdrawalReason withdrawalReason = memberWithdrawalAsOne.getWithdrawalReason();
log.debug(" withdrawalReason=" + withdrawalReason);
assertNotNull(withdrawalReason);
}
}
// 少なくとも一件以上は退会者の情報を持っていることのチェック(テスト成立確認)
assertTrue(existsOneOrMoreAtLeast);
}
会員Entityから会員退会情報Entityを取得して、
この例題の場合は、
退会理由Entityは会員退会情報があれば必須なので
親テーブルの取得の制限
親テーブルを取得するsetupSelect_
これは、
業務利用上、
よく勘違いされやすいのですが、
そちらの結合の方は、
結合先テーブルの条件で結果を絞り込むこと
次は、
結合して親テーブルの条件で結果を絞り込むやり方です
/**
* 結合した会員ステータスの名称が“正”で始まる会員一覧を検索
*
* @throws Exception
*/
public void test_ConditionBean_QueryForeign_ForeignTable_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.query().queryMemberStatus().setMemberStatusName_PrefixSearch("正");
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
final MemberStatusCB memberStatusCB = new MemberStatusCB();
memberStatusCB.query().setMemberStatusName_PrefixSearch("正");
final MemberStatus memberFormalizedStatus = memberStatusBhv.selectEntityWithDeletedCheck(memberStatusCB);
final String formalizedCode = memberFormalizedStatus.getMemberStatusCode();
for (Member member : memberList) {
log.debug("member=" + member);
final String memberStatusCode = member.getMemberStatusCode();
assertTrue("正式会員を示すコードであること", memberStatusCode.equals(formalizedCode));
assertNull("会員ステータス自身は取得はしていないこと", member.getMemberStatus());
}
}
先述の通り、
また、
ConditionBeanでソート指定
次はソートのやり方をみていきましょう。
ソートに関してはあまり深い概念は存在しませんので、
/**
* 会員アカウントの降順で並べた会員一覧を検索
*
* @throws Exception
*/
public void test_ConditionBean_Query_AddOrderBy_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.query().addOrderBy_MemberAccount_Desc();
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
String preMemberAccount = null;
for (Member member : memberList) {
final String memberName = member.getMemberName();
final String memberAccount = member.getMemberAccount();
log.debug("memberName=" + memberName + " memberAccount=" + memberAccount);
if (preMemberAccount == null) {
preMemberAccount = memberAccount;
continue;
}
if (preMemberAccount.compareTo(memberAccount) > 0) {
// OK
} else if (preMemberAccount.compareTo(memberAccount) == 0) {
// OK
} else {
fail();
}
}
}
AscなのかDescなのかは、
複数のソート条件を指定したい場合は、
ConditionBeanでの基本検索
それでは、
今までに登場してきた条件絞込み・
/**
* 以下の条件の会員一覧を検索。
* ・会員ステータスと退会理由を取得
* ・会員アカウントが“M”で始まる
* ・会員ステータス.表示順の昇順、会員.誕生日の降順、会員.会員IDの昇順でソート
*
* @throws Exception
*/
public void test_ConditionBean_BasicSelect_Tx() throws Exception {
// ## Arrange ##
final MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.setupSelect_MemberWithdrawalAsOne().withWithdrawalReason();
cb.query().setMemberAccount_PrefixSearch("M");
cb.query().queryMemberStatus().addOrderBy_DisplayOrder_Asc();
cb.query().addOrderBy_MemberBirthday_Desc();
cb.query().addOrderBy_MemberId_Asc();
// ## Act ##
final List memberList = memberBhv.selectList(cb);
// ## Assert ##
for (Member member : memberList) {
final String memberAccount = member.getMemberAccount();
final Date memberBirthday = member.getMemberBirthday();
final String memberStatusName = member.getMemberStatus().getMemberStatusName();
final MemberWithdrawal memberWithdrawalAsOne = member.getMemberWithdrawalAsOne();
String withdrawalReasonText = null;
if (memberWithdrawalAsOne != null) {
final WithdrawalReason withdrawalReason = memberWithdrawalAsOne.getWithdrawalReason();
withdrawalReasonText = withdrawalReason.getWithdrawalReasonText();
}
log.debug(memberAccount + " - " + memberBirthday + " - " + memberStatusName + " - " + withdrawalReasonText);
}
}
select MEMBER.MEMBER_ID
, MEMBER.MEMBER_NAME
, MEMBER.MEMBER_ACCOUNT
, MEMBER.MEMBER_STATUS_CODE
, MEMBER.MEMBER_BIRTHDAY
, MEMBER.VERSION_NO
, MEMBER.MEMBER_FORMALIZED_DATETIME
, MEMBER.REGISTER_DATETIME
, MEMBER.REGISTER_USER
, MEMBER.REGISTER_PROCESS
, MEMBER.UPDATE_DATETIME
, MEMBER.UPDATE_USER
, MEMBER.UPDATE_PROCESS
, dbfluteRelno_0.MEMBER_STATUS_CODE AS MEMBER_STATUS_CODE_0
, dbfluteRelno_0.MEMBER_STATUS_NAME AS MEMBER_STATUS_NAME_0
, dbfluteRelno_0.DISPLAY_ORDER AS DISPLAY_ORDER_0
, dbfluteRelno_2.MEMBER_ID AS MEMBER_ID_2
, dbfluteRelno_2.VERSION_NO AS VERSION_NO_2
, dbfluteRelno_2.REGISTER_DATETIME AS REGISTER_DATETIME_2
, dbfluteRelno_2.REGISTER_USER AS REGISTER_USER_2
, dbfluteRelno_2.REGISTER_PROCESS AS REGISTER_PROCESS_2
, dbfluteRelno_2.UPDATE_DATETIME AS UPDATE_DATETIME_2
, dbfluteRelno_2.UPDATE_USER AS UPDATE_USER_2
, dbfluteRelno_2.UPDATE_PROCESS AS UPDATE_PROCESS_2
, dbfluteRelno_2.WITHDRAWAL_REASON_CODE AS WITHDRAWAL_REASON_CODE_2
, dbfluteRelno_2.WITHDRAWAL_REASON_INPUT_TEXT AS WITHDRAWAL_REASON_INPUT_TEXT_2
, dbfluteRelno_2.WITHDRAWAL_DATETIME AS WITHDRAWAL_DATETIME_2
, dbfluteRelno_2_1_n2.WITHDRAWAL_REASON_TEXT AS WITHDRAWAL_REASON_TEXT_2_1
, dbfluteRelno_2_1_n2.DISPLAY_ORDER AS DISPLAY_ORDER_2_1
, dbfluteRelno_2_1_n2.WITHDRAWAL_REASON_CODE AS WITHDRAWAL_REASON_CODE_2_1
from MEMBER
left outer join MEMBER_STATUS dbfluteRelno_0
on MEMBER.MEMBER_STATUS_CODE = dbfluteRelno_0.MEMBER_STATUS_CODE
left outer join MEMBER_WITHDRAWAL dbfluteRelno_2
on MEMBER.MEMBER_ID = dbfluteRelno_2.MEMBER_ID
left outer join WITHDRAWAL_REASON dbfluteRelno_2_1_n2
on dbfluteRelno_2.WITHDRAWAL_REASON_CODE = dbfluteRelno_2_1_n2.WITHDRAWAL_REASON_CODE
where MEMBER.MEMBER_ACCOUNT like 'M%'
order by dbfluteRelno_0.DISPLAY_ORDER asc, MEMBER.MEMBER_BIRTHDAY desc, MEMBER.MEMBER_ID asc
次回
これにてConditionBeanの基本は一通り抑えました。実を言うと応用がたくさん存在するのですが、
次回は、
- 編注)
- 次回は、
2008年2月の公開予定です。