7

親オブジェクトがオプションの多対1の関係を持つテーブルがあります。問題は、テーブルがデフォルトでfkey列を0に設定されていることです。

選択するとき、fetch = "join"などを使用します。fkeyのデフォルトの0を使用して、ID 0の別のテーブルから選択するために何度も試行します。もちろんこれは存在しませんが、どうすればよいですか?存在しない関係をフェッチする際に20回以上循環しないように、0の値をNULLと同じように扱うようにHibernateに指示しますか?

<many-to-one name="device" lazy="false" class="Device" not-null="true" access="field" cascade="none" not-found="ignore">
<column name="DEVICEID" default="0" not-null="false"/>

4

3 に答える 3

6

これを行うには 2 つの方法があります。1 つはパフォーマンスが低下する方法で、もう 1 つは苦痛でぎこちない方法です。

醜い可能性のある方法は、ToOne 側で行われます。Hibernate Annotations を使用すると、次のようになります。

@Entity
public class Foo
{
    ...

    @ManyToOne
    @JoinColumn( name = "DEVICEID" )
    @NotFound( action = NotFoundAction.IGNORE )
    private Device device;

    ...
}

残念ながら、デバイスが null になる可能性があり、Hibernate が遅延デバイスを作成した場合、"device == null" は決して true にならないため、これはプリエンプティブ データベース ヒット (遅延読み込みなし) を強制します。

もう 1 つの方法は、ID 0 のリクエストをインターセプトして null を返すカスタム UserType を作成し、それを @Type を使用してDevice の主キーに割り当てることです。これにより、デバイスへの外部キーを持つ全員に 0 ~ null の解釈が強制されます。

于 2011-01-14T21:07:40.753 に答える
3

組み込みの Long 型を拡張する id-long 型を作成することでこれを修正できましたが、SQL から返された id が 0 の場合は、代わりに null を返します。これにより、DB でデフォルトの 0 を許可しながら、休止状態で遅延フェッチを停止することができました。

public class IdentifierLongType extends LongType implements IdentifierType {

@Override
public Object get(ResultSet rs, String name) throws SQLException {
    long i = rs.getLong(name);
    if (i == 0) {
        return null;
    } else {
        return Long.valueOf(i);
    }
}

}

明示的なデフォルト 0 を強制する理由は、Oracle がインデックス作成と null 値を奇妙に処理するためであり、「col is [not] null」よりも明示的な値を使用した方がクエリ パフォーマンスが向上することが示唆されます。

于 2011-01-26T05:53:03.023 に答える
0

オブジェクトのプライマリ/外部キー列としてプリミティブ型を使用していると思います。はいの場合は、ラッパー クラスを使用してみてください。プリミティブ型はデフォルト値を null にすることはできないためです。

于 2011-01-13T04:24:07.557 に答える