大規模な Hibernate クラスの分割
-
19-09-2019 - |
質問
私は 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 を使用したドメイン駆動設計
別の戦略をご存知の場合は、ぜひ共有してください。
よろしく、