El constructor sin argumentos es un requisito (herramientas como Hibernate usan la reflexión sobre este constructor para instanciar objetos).
Recibí esta respuesta de mano ondulada, pero ¿alguien podría explicar más? Gracias
El constructor sin argumentos es un requisito (herramientas como Hibernate usan la reflexión sobre este constructor para instanciar objetos).
Recibí esta respuesta de mano ondulada, pero ¿alguien podría explicar más? Gracias
The no-argument constructor is a requirement
es incorrecta , y todas las respuestas que proceden a explicar por qué esto es así, sin cuestionar si esto es así, (incluida la respuesta aceptada, que incluso ha recibido recompensa) son incorrectas . Vea esta respuesta: stackoverflow.com/a/29433238/773113Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
como en el caso en el que acabo de encontrarloRespuestas:
Hibernate, y el código en general que crea objetos a través de la reflexión se usa
Class<T>.newInstance()
para crear una nueva instancia de tus clases. Este método requiere un constructor público sin argumentos para poder crear una instancia del objeto. Para la mayoría de los casos de uso, proporcionar un constructor sin argumentos no es un problema.Hay trucos basados en la serialización que pueden evitar no tener un constructor sin argumentos, ya que la serialización usa jvm magic para crear objetos sin invocar al constructor. Pero esto no está disponible en todas las máquinas virtuales. Por ejemplo, XStream puede crear instancias de objetos que no tienen un constructor público sin argumentos, pero solo ejecutándose en un modo llamado "mejorado" que está disponible solo en ciertas VM. (Consulte el enlace para obtener más detalles). Los diseñadores de Hibernate seguramente eligieron mantener la compatibilidad con todas las máquinas virtuales y, por lo tanto, evitan tales trucos y utilizan el método de reflexión oficialmente admitido que
Class<T>.newInstance()
requiere un constructor sin argumentos.fuente
setAccessible(true)
tenerlo.ObjectInputStream
hace algo parecidosun.reflect.ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToGetInstanceOf, Object.class.getConstructor()).newInstance()
a crear instancias de objetos sin un constructor predeterminado (JDK1.6 para Windows)It can have package visibility and Hibernate should setAccessible(true)
. ¿it
Significa que la clase se instancia a través de la reflexión? Y queHibernate should setAccessible(true)
significaHibernate crea una instancia de sus objetos. Por lo tanto, debe poder instanciarlos. Si no hay un constructor sin argumentos , Hibernate no sabrá cómo instanciarlo, es decir, qué argumento pasar.
La documentación de hibernación dice:
Todas las clases persistentes deben tener un constructor predeterminado (que puede ser no público) para que Hibernate pueda instanciarlas usando
Constructor.newInstance()
. Se recomienda que tenga un constructor predeterminado con al menos visibilidad de paquete para la generación de proxy en tiempo de ejecución en Hibernate.fuente
Erm, lo siento a todos, pero Hibernate no requiere que sus clases deban tener un constructor sin parámetros. La especificación JPA 2.0 requiere, y esto es muy poco convincente en nombre de JPA. Otros marcos como JAXB también lo requieren, lo que también es muy poco convincente en nombre de esos marcos.
(En realidad, JAXB supuestamente permite las fábricas de entidades, pero insiste en instanciar estas fábricas por sí misma, requiriendo que tengan un constructor sin parámetros , adivina qué , que en mi libro es exactamente tan bueno como no permitir fábricas; qué tonto es eso !)
Pero Hibernate no requiere tal cosa.
Hibernate soporta un mecanismo de interceptación (ver "Interceptor" en la documentación ) que le permite crear una instancia de sus objetos con cualquier parámetro de constructor que necesiten.
Básicamente, lo que haces es que cuando configuras hibernate le pasas un objeto que implementa la
org.hibernate.Interceptor
interfaz, e hibernate invocará elinstantiate()
método de esa interfaz cada vez que necesite una nueva instancia de un objeto tuyo, por lo que tu implementación de ese método puedenew
sus objetos de la forma que desee.Lo he hecho en un proyecto y funciona de maravilla. En este proyecto hago las cosas a través de JPA siempre que sea posible, y solo uso funciones de Hibernate como el interceptor cuando no tengo otra opción.
Hibernate parece estar algo inseguro al respecto, ya que durante el inicio emite un mensaje de información para cada una de mis clases de entidad, diciéndome
INFO: HHH000182: No default (no-argument) constructor for class
yclass must be instantiated by Interceptor
, pero luego, más adelante, las instancia por interceptor, y está contento con eso.Para responder a la parte del "por qué" de la pregunta para herramientas distintas de Hibernate , la respuesta es "sin ninguna buena razón", y esto está probado por la existencia del interceptor de hibernación. Hay muchas herramientas que podrían haber admitido algún mecanismo similar para la creación de instancias de objetos del cliente, pero no lo hacen, por lo que crean los objetos por sí mismos, por lo que deben requerir constructores sin parámetros. Me siento tentado a creer que esto está sucediendo porque los creadores de estas herramientas piensan en sí mismos como programadores de sistemas ninja que crean marcos llenos de magia para ser utilizados por programadores de aplicaciones ignorantes, quienes (eso creen) nunca en sus sueños más locos tendrían un necesidad de construcciones tan avanzadas como el ... Patrón de fábrica . (Bueno,pensar eso. En realidad, no lo creo. Estoy bromeando.)
fuente
Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
lo siguiente, que ocurrió recientemente porquejavax.persistence.*;
se utiliza y soloorg.hibernate
al crear elSession, SessionFactory, and Configuration
La hibernación es un marco ORM que admite la estrategia de acceso al campo o la propiedad. Sin embargo, no admite el mapeo basado en constructores, ¿tal vez lo que le gustaría? - debido a algunos problemas como
1º ¿Qué pasa si tu clase contiene muchos constructores?
Como puede ver, se enfrenta a un problema de inconsistencia porque Hibernate no puede suponer qué constructor debería llamarse. Por ejemplo, suponga que necesita recuperar un objeto Person almacenado
¿Qué constructor debería llamar a Hibernate para recuperar un objeto Person? Puedes ver ?
2º Y finalmente, usando la reflexión, Hibernate puede instanciar una clase a través de su constructor no-arg. Así que cuando llamas
Hibernate instanciará su objeto Person de la siguiente manera
Que según la documentación de la API
Moraleja de la historia
es parecido a
Nada más
fuente
name
yage
? Si no, ¿usa otro constructor más tarde?En realidad, puede crear instancias de clases que no tienen constructor 0-args; puede obtener una lista de los constructores de una clase, elegir uno e invocarlo con parámetros falsos.
Si bien esto es posible, y supongo que funcionaría y no sería problemático, tendrás que aceptar que es bastante extraño.
Construir objetos de la forma en que lo hace Hibernate (creo que invoca el constructor de 0-arg y luego probablemente modifica los campos de la instancia directamente a través de Reflection. Quizás sepa cómo llamar a los setters) va un poco en contra de cómo se supone que se construye un objeto en Java: invoca al constructor con los parámetros adecuados para que el nuevo objeto sea el objeto que deseas. Creo que instanciar un objeto y luego mutarlo es algo "anti-Java" (o yo diría, anti Java teórico puro) - y definitivamente, si lo haces a través de la manipulación de campo directo, se encapsula y todo ese material de encapsulación elegante .
Creo que la forma correcta de hacer esto sería definir en el mapeo de Hibernate cómo se debe crear una instancia de un objeto a partir de la información en la fila de la base de datos usando el constructor adecuado ... pero esto sería más complejo, lo que significa que ambos Hibernate serían pares más complejo, el mapeo sería más complejo ... y todo más "puro"; y no creo que esto tenga una ventaja sobre el enfoque actual (aparte de sentirse bien haciendo las cosas "de la manera correcta").
Dicho esto, y viendo que el enfoque de Hibernate no es muy "limpio", la obligación de tener un constructor de 0-arg no es estrictamente necesaria, pero puedo entender un poco el requisito, aunque creo que lo hicieron de manera puramente "adecuada "motivos, cuando se desviaron del" camino correcto "(aunque por razones razonables) mucho antes de eso.
fuente
Hibernate necesita crear instancias como resultado de sus consultas (a través de la reflexión), Hibernate se basa en el constructor de entidades sin argumentos para eso, por lo que debe proporcionar un constructor sin argumentos. ¿Qué no está claro?
fuente
private
incorrecto un constructor? Estoy viendojava.lang.InstantiationException
incluso con unprivate
constructor para mi entidad JPA. referencia .Es mucho más fácil crear un objeto con un constructor sin parámetros a través de la reflexión y luego llenar sus propiedades con datos a través de la reflexión, que intentar hacer coincidir los datos con los parámetros arbitrarios de un constructor parametrizado, con cambios de nombres / conflictos de nombres, lógica no definida dentro del constructor, conjuntos de parámetros que no coinciden con las propiedades de un objeto, etcétera.
Muchos ORM y serializadores requieren constructores sin parámetros, porque los constructores paramterizados mediante reflexión son muy frágiles, y los constructores sin parámetros brindan estabilidad a la aplicación y control sobre el comportamiento del objeto al desarrollador.
fuente
Hibernate usa proxies para la carga diferida. Si no define un constructor o lo hace privado, es posible que algunas cosas sigan funcionando, las que no dependen del mecanismo de proxy. Por ejemplo, cargar el objeto (sin constructor) directamente usando la API de consulta.
Pero, si usa el método session.load (), se enfrentará a InstantiationException de la biblioteca del generador de proxy debido a la no disponibilidad del constructor.
Este chico informó una situación similar:
http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html
fuente
Consulte esta sección de la especificación del lenguaje Java que explica la diferencia entre clases internas estáticas y no estáticas: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
Una clase interna estática no es conceptualmente diferente a una clase general normal declarada en un archivo .java.
Dado que Hibernate necesita crear una instancia de ProjectPK independientemente de la instancia de Project, ProjectPK debe ser una clase interna estática o declararse en su propio archivo .java.
referencia org.hibernate.InstantiationException: No hay constructor predeterminado
fuente