Der Konstruktor ohne Argumente ist eine Anforderung (Tools wie Hibernate verwenden die Reflexion dieses Konstruktors, um Objekte zu instanziieren).
Ich habe diese handgewellte Antwort erhalten, aber könnte jemand weiter erklären? Vielen Dank
Der Konstruktor ohne Argumente ist eine Anforderung (Tools wie Hibernate verwenden die Reflexion dieses Konstruktors, um Objekte zu instanziieren).
Ich habe diese handgewellte Antwort erhalten, aber könnte jemand weiter erklären? Vielen Dank
The no-argument constructor is a requirement
die falsch ist , und alle Antworten, die erklären, warum dies so ist, ohne zu hinterfragen, ob dies tatsächlich so ist (einschließlich der akzeptierten Antwort, die sogar Kopfgeld erhalten hat), sind falsch . Siehe diese Antwort: stackoverflow.com/a/29433238/773113Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
wie in dem Fall, in dem ich gerade aufgetreten binAntworten:
Ruhezustand und Code im Allgemeinen, der Objekte über Reflektion erstellt, werden verwendet
Class<T>.newInstance()
, um eine neue Instanz Ihrer Klassen zu erstellen. Diese Methode erfordert einen öffentlichen Konstruktor ohne Argumente, um das Objekt instanziieren zu können. In den meisten Anwendungsfällen ist die Bereitstellung eines Konstruktors ohne Argumente kein Problem.Es gibt auf Serialisierung basierende Hacks, die umgehen können, wenn kein Konstruktor ohne Argumente vorhanden ist, da die Serialisierung mithilfe von JVM-Magie Objekte erstellt, ohne den Konstruktor aufzurufen. Dies ist jedoch nicht für alle VMs verfügbar. Beispielsweise kann XStream Instanzen von Objekten erstellen, die keinen öffentlichen Konstruktor ohne Argumente haben, sondern nur in einem sogenannten "erweiterten" Modus, der nur auf bestimmten VMs verfügbar ist. (Einzelheiten finden Sie unter dem Link.) Die Designer von Hibernate haben sich sicherlich dafür entschieden, die Kompatibilität mit allen VMs aufrechtzuerhalten, um solche Tricks zu vermeiden, und verwenden die offiziell unterstützte Reflektionsmethode, für
Class<T>.newInstance()
die ein Konstruktor ohne Argumente erforderlich ist.quelle
setAccessible(true)
darauf sein.ObjectInputStream
dient etwas in der Art dersun.reflect.ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToGetInstanceOf, Object.class.getConstructor()).newInstance()
Instanziierung von Objekten ohne Standardkonstruktor (JDK1.6 für Windows)It can have package visibility and Hibernate should setAccessible(true)
. Bedeutet das,it
dass die Klasse durch Reflexion instanziiert wird? Und was heißtHibernate should setAccessible(true)
das?Der Ruhezustand instanziiert Ihre Objekte. Es muss also in der Lage sein, sie zu instanziieren. Wenn es keinen Konstruktor ohne Argumente gibt, weiß Hibernate nicht, wie er instanziiert werden soll, dh welches Argument übergeben werden soll.
In der Dokumentation zum Ruhezustand heißt es:
Alle persistenten Klassen müssen über einen Standardkonstruktor verfügen (der nicht öffentlich sein kann), damit Hibernate sie mithilfe von instanziieren kann
Constructor.newInstance()
. Es wird empfohlen, einen Standardkonstruktor mit mindestens Paketsichtbarkeit für die Laufzeit-Proxy-Generierung in Hibernate zu haben.quelle
Ähm, entschuldigen Sie alle, aber Hibernate erfordert nicht , dass Ihre Klassen einen parameterlosen Konstruktor haben. Die JPA 2.0-Spezifikation erfordert dies, und dies ist im Namen von JPA sehr lahm. Andere Frameworks wie JAXB erfordern dies ebenfalls, was für diese Frameworks ebenfalls sehr lahm ist.
(Eigentlich erlaubt JAXB angeblich Entitätsfabriken, aber es besteht darauf, diese Fabriken selbst zu instanziieren, und erfordert, dass sie einen - erraten, was - parameterlosen Konstruktor haben , was in meinem Buch genauso gut ist, als Fabriken nicht zuzulassen; wie lahm ist das ? !)
Aber Hibernate erfordert so etwas nicht.
Der Ruhezustand unterstützt einen Abfangmechanismus (siehe "Abfangjäger" in der Dokumentation ), mit dem Sie Ihre Objekte mit den erforderlichen Konstruktorparametern instanziieren können.
Grundsätzlich übergeben Sie beim Einrichten des Ruhezustands ein Objekt, das die
org.hibernate.Interceptor
Schnittstelle implementiert , und der Ruhezustand ruft dann dieinstantiate()
Methode dieser Schnittstelle auf, wenn eine neue Instanz eines Objekts von Ihnen benötigt wird, damit Sie diese Methode implementieren könnennew
Ihre Objekte, wie Sie möchten.Ich habe es in einem Projekt gemacht und es funktioniert wie ein Zauber. In diesem Projekt mache ich Dinge über JPA, wann immer dies möglich ist, und ich verwende Hibernate-Funktionen wie den Interceptor nur, wenn ich keine andere Option habe.
Der Ruhezustand scheint etwas unsicher zu sein, da beim Start eine Infomeldung für jede meiner Entitätsklassen ausgegeben wird, die mir
INFO: HHH000182: No default (no-argument) constructor for class
undclass must be instantiated by Interceptor
, aber später instanziiere ich sie per Interceptor, und das freut mich.Um den "Warum" -Teil der Frage für andere Tools als "Ruhezustand" zu beantworten, lautet die Antwort "aus absolut keinem guten Grund", und dies wird durch die Existenz des Abfangjägers für den Ruhezustand bewiesen. Es gibt viele Tools, die einen ähnlichen Mechanismus für die Instanziierung von Clientobjekten hätten unterstützen können, aber dies ist nicht der Fall. Daher erstellen sie die Objekte selbst und benötigen daher parameterlose Konstruktoren. Ich bin versucht zu glauben, dass dies geschieht, weil die Entwickler dieser Tools sich selbst als Ninja-Systemprogrammierer betrachten, die Frameworks voller Magie erstellen, die von ignoranten Anwendungsprogrammierern verwendet werden, die (so denken sie) in ihren wildesten Träumen niemals eine haben würden Notwendigkeit für so fortschrittliche Konstrukte wie das ... Factory Pattern . (In Ordnung,so zu denken. Das glaube ich eigentlich nicht . Ich mache Witze.)
quelle
Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
das Folgende, das kürzlich aufgetreten ist, weiljavax.persistence.*;
es verwendet wird und nurorg.hibernate
beim Erstellen desSession, SessionFactory, and Configuration
Der Ruhezustand ist ein ORM-Framework, das die Feld- oder Eigenschaftszugriffsstrategie unterstützt. Konstruktorbasiertes Mapping wird jedoch nicht unterstützt - was möchten Sie vielleicht? - wegen einiger Probleme wie
1º Was passiert, wenn Ihre Klasse viele Konstruktoren enthält?
Wie Sie sehen, haben Sie es mit einem Problem der Inkonsistenz zu tun, da Hibernate nicht annehmen kann, welcher Konstruktor aufgerufen werden soll. Angenommen, Sie müssen ein gespeichertes Personenobjekt abrufen
Welchen Konstruktor sollte Hibernate aufrufen, um ein Personenobjekt abzurufen? Kannst du sehen ?
2º Und schließlich kann Hibernate durch Reflektion eine Klasse über seinen Konstruktor ohne Argumente instanziieren. Also wenn du anrufst
Durch den Ruhezustand wird Ihr Personenobjekt wie folgt instanziiert
Welche laut API-Dokumentation
Moral der Geschichte
ist ähnlich wie
Nichts anderes
quelle
name
undage
? Wenn nicht, wird später ein anderer Konstruktor verwendet?Tatsächlich können Sie Klassen instanziieren, die keinen 0-args-Konstruktor haben. Sie können eine Liste der Konstruktoren einer Klasse abrufen, einen auswählen und ihn mit falschen Parametern aufrufen.
Dies ist zwar möglich und ich denke, es würde funktionieren und wäre nicht problematisch, aber Sie müssen zustimmen, dass das ziemlich seltsam ist.
Das Konstruieren von Objekten wie im Ruhezustand (ich glaube, es ruft den 0-arg-Konstruktor auf und ändert dann wahrscheinlich die Felder der Instanz direkt über Reflection. Vielleicht weiß es, wie man Setter aufruft) widerspricht ein wenig der Art und Weise, wie ein Objekt konstruiert werden soll Java - Rufen Sie den Konstruktor mit den entsprechenden Parametern auf, damit das neue Objekt das gewünschte Objekt ist. Ich glaube, dass das Instanziieren eines Objekts und das anschließende Mutieren etwas "Anti-Java" ist (oder ich würde sagen, anti-reines theoretisches Java) - und definitiv, wenn Sie dies über direkte Feldmanipulation tun, geht es um Kapselung und all das ausgefallene Kapselungsmaterial .
Ich denke, dass der richtige Weg, dies zu tun, darin besteht, im Hibernate-Mapping zu definieren, wie ein Objekt aus den Informationen in der Datenbankzeile mit dem richtigen Konstruktor instanziiert werden soll ... aber dies wäre komplexer - was bedeutet, dass beide Hibernate gerade wären komplexer wäre das Mapping komplexer ... und alles "reiner"; und ich denke nicht, dass dies einen Vorteil gegenüber dem gegenwärtigen Ansatz hätte (abgesehen davon, dass man sich gut fühlt, wenn man Dinge "richtig" macht).
Angesichts der Tatsache, dass der Hibernate-Ansatz nicht sehr "sauber" ist, ist die Verpflichtung, einen 0-arg-Konstruktor zu haben, nicht unbedingt erforderlich, aber ich kann die Anforderung etwas verstehen, obwohl ich glaube, dass sie dies auf rein "richtige Weise" getan haben "Gründe, als sie viel früher vom" richtigen Weg "abgewichen sind (wenn auch aus vernünftigen Gründen).
quelle
Hibernate muss Instanzen als Ergebnis Ihrer Abfragen erstellen (über Reflection). Hibernate verwendet dafür den Konstruktor no-arg von Entitäten, sodass Sie einen Konstruktor no-arg bereitstellen müssen. Was ist nicht klar?
quelle
private
Konstruktor falsch? Ich sehejava.lang.InstantiationException
sogar mit einemprivate
Konstruktor für meine JPA-Entität. Referenz .Es ist viel einfacher, ein Objekt mit einem parameterlosen Konstruktor durch Reflexion zu erstellen und dann seine Eigenschaften durch Reflexion mit Daten zu füllen, als zu versuchen, Daten mit beliebigen Parametern eines parametrisierten Konstruktors abzugleichen, mit sich ändernden Namen / Namenskonflikten, undefinierter Logik innerhalb des Konstruktors. Parametersätze, die nicht mit den Eigenschaften eines Objekts übereinstimmen, usw.
Viele ORMs und Serializer erfordern parameterlose Konstruktoren, da parametrisierte Konstruktoren durch Reflexion sehr fragil sind und parameterlose Konstruktoren sowohl Stabilität für die Anwendung als auch Kontrolle über das Objektverhalten für den Entwickler bieten.
quelle
Hibernate verwendet Proxys zum verzögerten Laden. Wenn Sie einen Konstruktor nicht definieren oder privat machen, funktionieren möglicherweise noch einige Dinge - diejenigen, die nicht vom Proxy-Mechanismus abhängen. Laden Sie beispielsweise das Objekt (ohne Konstruktor) direkt über die Abfrage-API.
Wenn Sie jedoch die session.load-Methode () verwenden, tritt aufgrund der Nichtverfügbarkeit des Konstruktors eine InstantiationException aus der Proxy-Generator-Bibliothek auf.
Dieser Typ berichtete über eine ähnliche Situation:
http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html
quelle
Lesen Sie diesen Abschnitt der Java-Sprachspezifikation, in dem der Unterschied zwischen statischen und nicht statischen inneren Klassen erläutert wird: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
Eine statische innere Klasse unterscheidet sich konzeptionell nicht von einer regulären allgemeinen Klasse, die in einer Java-Datei deklariert ist.
Da Hibernate ProjectPK unabhängig von der Project-Instanz instanziieren muss, muss ProjectPK entweder eine statische innere Klasse sein oder in einer eigenen Java-Datei deklariert sein.
Referenz org.hibernate.InstantiationException: Kein Standardkonstruktor
quelle