1

データベースビューのHibernateエンティティマッピングに取り組んでいます。それに対して基準クエリを実行すると、hibernateは不正なSQLを生成しています。私のマッピングの問題が何であるかを理解する助けがあれば大歓迎です!

データベースビューから取得しようとしている2つのマップされたエンティティがあります。ビューには他の列はなく、各エンティティのFKのみがあります。ビューには各プライマリエンティティの行があるため、これらのFKの1つをプライマリキーとして扱うことができます。したがって、ビューのDBスキーマは次のようになります。

primary(primary_id, some_other_fields)
history(history_id, primary_id, some_other_fields)
view_latest_status_history(primary_id, history_id)

マップされたすべての履歴レコードではなく、各プライマリの最新の履歴のみを取得するため、ビューが使用されていることに注意してください。ビューに使用しているオブジェクトとエンティティの注釈は次のとおりです。

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Table(name = "view_latest_status_history")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ViewLatestStatusHistoryRow implements Serializable {
    private Primary primary;
    private History history;

    /**
     * @return Returns the history.
     */
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinColumn(name = "history_id", nullable = true)
    @AccessType("field")
    public History getHistory() {
        return history;
    }

    //equals() and hashCode() implementations are omitted

    /**
     * @return Returns the primary.
     */
    @Id
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinColumn(name = "primary_id", nullable = false)
    @AccessType("field")
    public Primary getPrimary() {
        return primary;
    }
}

PrimaryオブジェクトとHistoryオブジェクトの両方に、完全な作業エンティティの注釈があります。

私の基準設定:

criteria.add(Restrictions.in("primary", [collection of primary objects]));
criteria.setFetchMode("primary", FetchMode.JOIN);
criteria.setFetchMode("history", FetchMode.JOIN);

そして(間違った)生成されたSQL:

select this_.primary as primary78_1_, this_.primary_id as prim2_78_1_, primary2_.history_id as unique1_56_0_, ...history fields
from DB_CATALOG.dbo.view_latest_status_history this_ 
left outer join DB_CATALOG.dbo.history primary2_ on this_.primary_id=primary2_.primary_id 
where this_.specChange in (?, ?...)

プロジェクトのDBスキーマの詳細を編集するときに、いくつかのことをいじくりまわしたかもしれませんが、要点は、「select」句の最初のフィールドが間違っていることです。

this_.primary(view_latest_status_history.primary)はフィールドではありません。フィールドはprimary_idと呼ばれる必要があります。これは、プライマリフィールドの@Idアノテーションと関係があると思いますか?これを修正する方法はありますか?@Idを削除すると、エンティティに主キーがないというエラーが表示されます。

アップデート:

(以下に示すように)結合テーブル表記を使用してビューをフィールドとしてマップしなくなりました。アノテーションを以下のように改訂しました。このソリューションはHQLで正しく機能し、hbm2ddlが有効になっている場合に期待されるスキーマを生成しますが、基準クエリを使用して再テストしていません。

@Entity
@Table(name = "view_latest_status_history")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class ViewLatestStatusHistoryRow implements Serializable {
    private String id;
    private Primary primary;
    private History history;

    /**
     * @return Returns the history.
     */
    @OneToOne(optional = true)
    @JoinColumn(name = "history_id", nullable = true)
    @AccessType("field")
    public History getHistory() {
        return history;
    }

    //equals() and hashCode() implementations are omitted

    @Id
    @Column(name = "primary_id", nullable = false)
    @Override
    @AccessType(value = "field")
    public String getId() {
        return id;
    }

    /**
     * @return Returns the primary.
     */
    @PrimaryKeyJoinColumn(name = "primary_id", referencedColumnName = "unique_id")
    @OneToOne(optional = false)
    @AccessType("field")
    public Primary getPrimary() {
        return primary;
    }
}
4

1 に答える 1

1

これは間違いなく@Id注釈によるものです。この場合、primary_id は主キーではありません。同じプロパティに @Id と @ManyToOne を設定することも現実的には不可能です。

お聞きしたいのですがViewLatestStatusHistoryRow、そもそもなぜエンティティとしてマッピングしているのですか? あなたがそれを持続するつもりはありません。最新の履歴エントリをプライマリ (多対 1) に直接 (読み取り専用として) マッピングし、ビューを結合テーブルとして使用することを検討してください。

于 2009-09-17T22:51:38.337 に答える