Zerschlagung eine große Ruhe Klasse
-
19-09-2019 - |
Frage
Ich habe eine Hibernate-Klasse, die im Wesentlichen um Lasten von Sammlungen nur ein Wrapper ist.
So ist die Klasse (massiv vereinfacht / pseudo) so etwas wie:
@Entity public class MyClass { @OneToMany Map1 @OneToMany Map2 @OneToMany Map3 AddToMap1(); AddToMap2(); AddToMap3(); RemoveFromMap1(); RemoveFromMap2(); RemoveFromMap3(); DoWhateverWithMap1(); DoWhateverWithMap2(); DoWhateverWithMap3(); }
usw. Jede dieser Karten dann hat ein paar Methoden mit ihm verbunden (hinzufügen / entfernen / abfragen / etc).
Wie Sie sich vorstellen können, als ich den 10. Sammlung hinzugefügt oder so, wird die Klasse ein bisschen lächerlich in der Größe zu bekommen.
Was ich würde gerne tun, etwas entlang der Linien von:
@Entity public class MyClass { ClassWrappingMap1; ClassWrappingMap2; ClassWrappingMap3; }
Mit all den verschiedenen Methoden in diesen Klassen eingewickelt:
public class ClassWrappingMap1 { @OneToMany Map AddToMap(); RemoveFromMap(); DoWhateverWithMap(); }
Ich dachte, vielleicht könnte ich @Embedded
für diese, aber ich glaube nicht, es zu bekommen, um in der Lage zu arbeiten (Hibernate funktioniert einfach nicht einmal versuchen, die Karte innerhalb des wrapperClass bestehen bleiben).
Hat jemand schon mal so etwas wie dies zuvor getan? Irgendwelche Hinweise?
Vielen Dank,
Ned
Lösung
Hibernate Handbuch für Anmerkungen Staaten folgende :
Während man nicht durch die EJB3-Spezifikation unterstützt, Hibernate Annotations können Sie Assoziation Anmerkungen in einem eingebetteten Objekt verwenden (dh @ * TOONE noch @ * Tomany). Um die Assoziation Spalten außer Kraft setzen Sie können @AssociationOverride verwenden.
So Ihre Verpackung Ansatz sollte funktionieren.
Zunächst einmal sollten Sie alle Protokolldateien usw. für alle damit verbundenen Fehler überprüfen.
Sie könnte so etwas wie diese versuchen:
- In Ihrer Master-Klasse (MyClass)
@Entity public class MyClass { @Embedded ClassWrappingMap1 map1; }
- Und in der Verpackung Klasse
@Embeddable public class ClassWrappingMap1 { @OneToMany Map map1; }
Beachten Sie, dass ClassWrappingMap1
@Embeddable
Annotation verwendet. Doch nach docs der @Embeddable Anmerkung sollte nicht erforderlich sein, sollte es Standard sein, wenn @Embedded Anmerkung verwendet wird.
Stellen Sie sicher, dass jeder ClassWrappingMap Klasse ordnet eine andere Spalte in der Datenbank. Auch ClassWrappingMap Klassen sollten keinen Primärschlüssel (@Id
oder @EmbeddedId
Spalten) haben.
Andere Tipps
Obwohl ich keine Standard Strategie wissen, wann eine Wrapper-Klasse verwenden, können Sie eine Hibernate Interceptor verwenden, um Ihre Wrapper der Initialisierung durch zwingende Beiladen Methode. So etwas wie
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;
}
}
Kümmert sich wie folgt zusammen:
Ein Client diese Abfangjäger verwenden, müssen Session-Eigenschaft
So Ihr Code sieht wie diese
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();
oder Feder AOP verwenden, um die gleiche Aufgabe zu tun. Siehe Domain Driven Design mit Spring und Hibernate
Wenn Sie eine andere Strategie kennen, teilen Sie es mit uns.
Grüße,