web-dev-qa-db-ja.com

埋め込まれたHibernateエンティティをnull不可にすることはできますか?

私が欲しいもの:

@Embedded(nullable = false)
private Direito direito;

ただし、ご存知のように、@ Embeddableにはそのような属性はありません。

これを行う正しい方法はありますか?回避策は必要ありません。

34
André Chalella

埋め込み可能なコンポーネント(または複合要素、それらを呼び出したいものは何でも)は通常、複数のプロパティを含み、したがって複数の列にマップされます。したがって、nullであるコンポーネント全体は、さまざまな方法で処理できます。 J2EE仕様は、何らかの方法を規定していません。

Hibernateは、すべてのプロパティがNULLの場合(およびその逆の場合)、コンポーネントをNULLと見なします。したがって、プロパティの1つ(任意)をnullでないように宣言して(@Embeddable内または@AttributeOverride@Embeddedの一部として)、目的を達成できます。

または、Hibernate Validatorを使用している場合は、プロパティに@NotNullアノテーションを付けることができますが、これはアプリレベルのチェックのみになり、dbレベルにはなりません。

37
ChssPly76

Hibernate 5.1以降、「hibernate.create_empty_composites.enabled」を使用してこの動作を変更することができます( https://hibernate.atlassian.net/browse/HHH-761 を参照)

23
user158037

@Embeddableとマークされたクラスにダミーフィールドを追加します。

@Formula("0")
private int dummy;

https://issues.jboss.org/browse/HIBERNATE-5 を参照してください。

11

以前に行った提案のどちらにもそれほど興奮していなかったので、これを処理できるアスペクトを作成しました。

これは完全にはテストされておらず、埋め込みオブジェクトのコレクションに対しても確実にテストされていないため、購入者は注意してください。しかし、これまでのところうまくいくようです。

基本的に、ゲッターを@Embeddedフィールドにインターセプトし、フィールドにデータが入力されていることを確認します。

public aspect NonNullEmbedded {

    // define a pointcut for any getter method of a field with @Embedded of type Validity with any name in com.ia.domain package
    pointcut embeddedGetter() : get( @javax.persistence.Embedded * com.company.model..* );


    /**
     * Advice to run before any Embedded getter.
     * Checks if the field is null.  If it is, then it automatically instantiates the Embedded object.
     */
    Object around() : embeddedGetter(){
        Object value = proceed();

        // check if null.  If so, then instantiate the object and assign it to the model.
        // Otherwise just return the value retrieved.
        if( value == null ){
            String fieldName = thisJoinPoint.getSignature().getName();
            Object obj = thisJoinPoint.getThis();

            // check to see if the obj has the field already defined or is null
            try{
                Field field = obj.getClass().getDeclaredField(fieldName);
                Class clazz = field.getType();
                value = clazz.newInstance();
                field.setAccessible(true);
                field.set(obj, value );
            }
            catch( NoSuchFieldException | IllegalAccessException | InstantiationException e){
                e.printStackTrace();
            }
        }

        return value;
    }
}
1
Eric B.

Nullsafeゲッターを使用できます。

public Direito getDireito() {
    if (direito == null) {
        direito = new Direito();
    }
    return direito;
}
0
felipebatista