0

私のアプリには、2つのテーブルがあります。決済結果と決済状態決済結果には、名前、タイプなどの基本データが含まれています。決済状態は、決済結果との関係の「多」側であり、決済結果PKとステータスを多対多で構成します。 -PKおよび日付として1つのID。データ例:

Settlement Result
------------------------------
ID| Name      | Sth
------------------------------
1 | Some Name | Something more
2 | Name2     | more2

Settlement State
----------
Result's ID | StatusId     | Date 
------------------------------
1           | 1            | some date
1           | 2            | date
1           | 3            | date
2           | 1            | date

ここで、HQL / Plain SQLを使用して、決済結果からの行を選択します。たとえば、ステータスID == 3ですが、IDが高い行は選択しません。

考えられるステータスはいくつかあります。

Status ID | Desc
-----------------
1 | Created
2 | Confirmed
3 | Accepted
4 | Rejected

SettlementResultを作成するときは、常に「ワークフロー」があります。まず、結果のステータスは作成済み(ID 1)です。次に、拒否(ID 4)または確認(ID 2)することができます。その後、再びそれを受け入れるか拒否することができます。

したがって、1つのSettlementResultは、ステータスIDが1,2,4(Created、Confirmed、ただしAccepted = Rejectedではない)のSettlementStatesを持つことができます。

問題は、特定のステータス(たとえば、作成済み)を持つSettlementResultsのみを選択したいということです。」

このようなHQLクエリを使用すると:

Query query = session.createSQLQuery( "select distinct s from SettlementResult s join s.settlementStates states where states.settlementStatePK.status.statusId == 1" );

ステータスが1、2、3の場合でも、すべての決済結果が返されます(コレクションには、作成されたIDと等しいIDの結果が含まれているため)。

たとえば、Created [ID 1]が必要な場合、特定のステータスのみを持つ決済結果のみを選択することは可能ですか。決済状態ステータスが1のみで、2、3、または4ステータスはありません。ステータスID3の決済状態を選択すると、ステータスID = 1,2,3の決済状態であるが、4ではない場合に受け入れることができmax[status.id]ます。

@Entity
@Table(name = "SETTLEMENT_STATE")
public class SettlementState
{
    @EmbeddedId
    private SettlementStatePK settlementStatePK;

    @Column(name = "DESCRIPTION")
    private String description;

    @Column(name = "STATUS_DTTM")
    private Date statusDate;
}

@Embeddable
public class SettlementStatePK implements Serializable
{
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "STATUS_ID")
    private Status status;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SETTLEMENT_RESULT_ID")
    private SettlementResult settlementResult;
}

@Entity
@Table(name = "SETTLEMENT_RESULT")
public class SettlementResult implements Serializable
{
    @Id
    @Column(name = "SETTLEMENT_RESULT_ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "STATUS_ID")
    private Status status;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "MODEL_GROUP_ID")
    private SettlementModelGroup settlementModelGroup;

    @Column(name = "\"MODE\"")
    private Integer mode;

    @Column(name = "CREATED_DTTM")
    private Date createdDate;

    @Column(name = "DESCRIPTION")
    private String description;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "settlementStatePK.settlementResult")
    private List<SettlementState> settlementStates;
}
4

1 に答える 1

1

ここには 2 つのオプションがあります。

クエリが表示された場合は、 SettlementResult オブジェクトを取得しています

Query query = session.createSQLQuery( "select distinct s from SettlementResult s join s.settlementStates states where states.settlementStatePK.status.statusId == 1" );

クエリは完璧ですが、親オブジェクト SettlementResult があり、OneToMany コレクションの決済状態にアクセスすると、休止状態は SettlementResult PK に基づいてそれらすべてをロードします (これはあなたが観察したものでもあります)。

したがって、オプション 1 : 子から親へ移動し ます。これは、クエリから SettlementState オブジェクトを次のように返すことを意味します。

Query query = session.createSQLQuery( "select distinct states from SettlementResult s join s.settlementStates states where states.settlementStatePK.status.statusId == 1" );

SettlementState クラスで SettlementResult に ManyToOne を定義しているため、状態オブジェクトから SettlementResult にアクセスできます。この場合、探している SettlementResult オブジェクトが確実に得られます。

オプション 2: SettlementState オブジェクトを分割する オプション 1 は機能しますが、この解決策は奇妙に思えるかもしれません。したがって、この問題を解決する最善の方法は、Settlement State オブジェクトを分割することです (問題で説明されているように)。

1. RejectedSettlementState
2. NonRejectedSettlementState

これら 2 つのクラスは、1 つの基本抽象クラス (SettlementState) を拡張します。ステータス ID に識別式を定義できます。これらのクラスを取得したら、これらのサブクラスを SettlementResult に関連付けることができます。必要なクラスは次のとおりです(sudo)

@DiscriminatorForumla("case when status_id == 4 then "REJECTEDSTATE" else "NONREJECTEDSTATE" end")
public abstract class SettlementState{
...
// Define all of your common fields in this parent class
}

@DiscriminatorValue("REJECTEDSTATE")
public class RejectedSettlementState extends SettlementState{
...
// define only fields specific to this rejected state
}


@DiscriminatorValue("NOTREJECTEDSTATE")
public class NonRejectedSettlementState extends SettlementState{
...
// define only fields specific to this non-rejected state
}

今 SettlementResult クラス

public class SettlementResult{

@OneToMany(fetch = FetchType.LAZY, mappedBy = "settlementStatePK.settlementResult")
private List<RejectedSettlementState> rejectedSettlementStates;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "settlementStatePK.settlementResult")
private List<NonRejectedSettlementState> nonRejectedSettlementStates;

}

したがって、これらのオブジェクトがすべて揃ったら。その後、ステータスのクエリは必要ありません。親オブジェクトの SettlementResult をロードするだけで、拒否された、または拒否されていない決済ステータスにアクセスできます。Hibernate は式の条件を使用して、SettlementResult クラスで定義されている遅延ロードを使用してこれらのコレクションを初期化します。

注: 私にとってはどちらの解決策も受け入れられますが、システムにどちらを配置するかによって異なります。2 番目のオプションは、将来のためにより多くのエッジを提供します。

その他の情報: お尋ねください! 私はあなたがこの考えを理解できるように最善を尽くしました:)。幸運を!

于 2012-12-16T18:47:18.330 に答える