質問

私は Hibernate クラスを持っていますが、これは本質的には大量のコレクションの単なるラッパーです。

したがって、クラスは(大幅に簡略化/擬似的に)次のようになります。

@Entity  
public class MyClass {

  @OneToMany  
  Map1

  @OneToMany  
  Map2

  @OneToMany   
  Map3

  AddToMap1();  
  AddToMap2();  
  AddToMap3();  
  RemoveFromMap1();  
  RemoveFromMap2();  
  RemoveFromMap3();  
  DoWhateverWithMap1();  
  DoWhateverWithMap2();  
  DoWhateverWithMap3();  

}

等これらの各マップには、それに関連付けられたいくつかのメソッド (追加/削除/問い合わせなど) があります。

ご想像のとおり、10 番目くらいのコレクションを追加する頃には、クラスのサイズが少しとんでもないものになってしまいます。

私がやりたいのは次のようなことです。

 
@Entity  
public class MyClass {

  ClassWrappingMap1;

  ClassWrappingMap2;

  ClassWrappingMap3;
}

さまざまなメソッドをすべてこれらのクラスにラップすると、次のようになります。

public class ClassWrappingMap1 {

  @OneToMany
  Map

  AddToMap();  
  RemoveFromMap();  
  DoWhateverWithMap();  

}

もしかしたら使えるかもしれないと思ったのですが、 @Embedded これについては、私はそれを機能させることができないようです(Hibernateは単にwrapperClass内でMapを永続化しようともしません)。

これまでにこのようなことをした人はいますか?ヒントはありますか?

どうもありがとう、
ネッド

役に立ちましたか?

解決

アノテーションのための Hibernate マニュアル 次のように述べています。

EJB3 仕様ではサポートされていませんが、Hibernate アノテーションを使用すると、埋め込み可能なオブジェクト (つまり、@*ToOne または @*ToMany) で関連付けアノテーションを使用できます。関連列をオーバーライドするには、@AssociationOverride を使用できます。

したがって、ラッピングアプローチは機能するはずです。


まず、すべてのログ ファイルなどに関連するエラーがないか確認する必要があります。

次のようなことを試すことができます。

  • マスタークラス (MyClass) 内
@Entity  
public class MyClass {

  @Embedded
  ClassWrappingMap1 map1;
}
  • そしてラッピングクラスでは
@Embeddable
public class ClassWrappingMap1 {

  @OneToMany
  Map map1;

}

注目してください ClassWrappingMap1 用途 @Embeddable 注釈。ただし、ドキュメントによると、@Embeddable アノテーションは必要ありません。@Embedded アノテーションが使用される場合はデフォルトである必要があります。

すべての ClassWrappingMap クラスがデータベース内の異なる列をマップしていることを確認してください。また、ClassWrappingMap クラスには主キー (@Id または @EmbeddedId 列)。

他のヒント

ラッパークラスを使用するときのデフォルトの戦略はわかりませんが、Hibernate Interceptor を使用してラッパーをオーバーライドすることでラッパーを初期化できます。 onLoad 方法。何かのようなもの

public class WrapperInterceptor extends EmptyInterceptor {

    private Session session;

    public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        if (entity instanceof MyClass) {
             MyClass myClass = (MyClass) entity;

             Query query = session.createQuery(<QUERY_TO_RETRIEVE_WRAPPED_ENTITY_GOES_HERE>);

             WrappedEntity wrappedEntity = query.list().get(0);

             myClass.setWrapperClass(new WrapperClass(wrappedEntity));
        }
    }

    public void setSession(Session session) {
        this.session = session;
    }
}

次のことに注意します。

このインターセプターを使用するクライアントは、Session プロパティを設定する必要があります

したがって、コードは次のようになります

WrapperInterceptor interceptor = new WrapperInterceptor();

Session session = sessionFactory().openSession(interceptor);

Transaction tx = session.beginTransaction();

interceptor.setSession(session);

MyClass myClass = (MyClass) session.get(newItem, myClassId); // Triggers onLoad event

tx.commit();
session.close();

または、Spring AOP を使用して同じタスクを実行します。見る Spring と Hibernate を使用したドメイン駆動設計

別の戦略をご存知の場合は、ぜひ共有してください。

よろしく、

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top