O construtor sem argumento é um requisito (ferramentas como o Hibernate usam reflexão neste construtor para instanciar objetos).
Recebi uma resposta ondulada, mas alguém poderia explicar melhor? obrigado
java
hibernate
orm
factory-pattern
unj2
fonte
fonte
The no-argument constructor is a requirement
está errada e todas as respostas que explicam por que isso é assim, sem questionar se é de fato assim, (incluindo a resposta aceita, que recebeu até recompensa) estão erradas . Veja esta resposta: stackoverflow.com/a/29433238/773113Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
como no caso que eu acabei de encontrarRespostas:
O Hibernate e o código em geral que cria objetos via reflexão usam
Class<T>.newInstance()
para criar uma nova instância de suas classes. Este método requer um construtor público sem argumentos para poder instanciar o objeto. Para a maioria dos casos de uso, fornecer um construtor sem argumentos não é um problema.Existem hacks baseados na serialização que podem contornar a falta de um construtor no-arg, já que a serialização usa a magia jvm para criar objetos sem invocar o construtor. Mas isso não está disponível em todas as VMs. Por exemplo, o XStream pode criar instâncias de objetos que não têm um construtor não-arg público, mas apenas executando em um modo chamado "aprimorado", que está disponível apenas em certas VMs. (Veja o link para detalhes.) Os designers do Hibernate certamente escolheram manter a compatibilidade com todas as VMs e, portanto, evitam tais truques e usam o método de reflexão oficialmente suportado que
Class<T>.newInstance()
requer um construtor sem arg.fonte
setAccessible(true)
nele.ObjectInputStream
faz algosun.reflect.ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToGetInstanceOf, Object.class.getConstructor()).newInstance()
semelhante a instanciar objetos sem construtor padrão (JDK1.6 para Windows)It can have package visibility and Hibernate should setAccessible(true)
. Será queit
significa o ser classe instanciado via reflexão? E o que issoHibernate should setAccessible(true)
significa?O Hibernate instancia seus objetos. Portanto, ele precisa ser capaz de instanciá-los. Se não houver um construtor sem arg, o Hibernate não saberá como instanciá-lo, isto é, qual argumento passar.
A documentação de hibernação diz:
Todas as classes persistentes devem ter um construtor padrão (que pode ser não público) para que o Hibernate possa instanciá-las usando
Constructor.newInstance()
. É recomendado que você tenha um construtor padrão com pelo menos visibilidade de pacote para geração de proxy em tempo de execução no Hibernate.fonte
Erm, desculpe a todos, mas o Hibernate não requer que suas classes tenham um construtor sem parâmetros. A especificação JPA 2.0 exige isso, e isso é muito ruim em nome do JPA. Outras estruturas, como JAXB, também exigem isso, o que também é muito ruim em nome dessas estruturas.
(Na verdade, JAXB supostamente permite fábricas de entidades, mas insiste em instanciar essas fábricas por si só, exigindo que elas tenham um construtor - adivinhe - sem parâmetros , que em meu livro é exatamente tão bom quanto não permitir fábricas; quão ruim é isso !)
Mas o Hibernate não exige tal coisa.
O Hibernate suporta um mecanismo de interceptação, (veja "Interceptor" na documentação ), que permite a você instanciar seus objetos com quaisquer parâmetros de construtor que eles precisem.
Basicamente, o que você faz é que quando você configura o hibernate você passa um objeto que implementa a
org.hibernate.Interceptor
interface, e o hibernate irá então invocar oinstantiate()
método daquela interface sempre que precisar de uma nova instância de um objeto seu, então a implementação desse método podenew
seus objetos da maneira que quiser.Eu fiz isso em um projeto e funciona como um encanto. Neste projeto, faço as coisas via JPA sempre que possível e só uso recursos do Hibernate, como o interceptor, quando não tenho outra opção.
O Hibernate parece um tanto inseguro quanto a isso, já que durante a inicialização ele emite uma mensagem de informação para cada uma das minhas classes de entidade, dizendo-me
INFO: HHH000182: No default (no-argument) constructor for class
eclass must be instantiated by Interceptor
, mas depois eu as instancio por interceptor, e ele está feliz com isso.Para responder ao "por que" parte da pergunta para outras ferramentas além do Hibernate , a resposta é "sem nenhuma boa razão", e isso é comprovado pela existência do interceptor do Hibernate. Existem muitas ferramentas por aí que poderiam oferecer suporte a algum mecanismo semelhante para a instanciação de objetos do cliente, mas não suportam, portanto, eles criam os objetos por si próprios, portanto, precisam exigir construtores sem parâmetros. Estou tentado a acreditar que isso está acontecendo porque os criadores dessas ferramentas pensam em si mesmos como programadores de sistemas ninja que criam frameworks cheios de magia para serem usados por programadores de aplicativos ignorantes, que (assim eles acham) nunca teriam em seus sonhos mais selvagens um necessidade de construções avançadas como o ... Padrão de fábrica . (OK,pensar assim. Eu realmente não penso assim. Estou brincando.)
fonte
Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Student
recentemente porquejavax.persistence.*;
é utilizado e somenteorg.hibernate
ao criar oSession, SessionFactory, and Configuration
O hibernate é uma estrutura ORM que suporta estratégia de acesso a campo ou propriedade. No entanto, ele não suporta mapeamento baseado em construtor - talvez o que você gostaria? - por causa de alguns problemas como
1º O que acontece se sua classe contiver muitos construtores
Como você pode ver, você lida com um problema de inconsistência porque o Hibernate não pode supor que construtor deve ser chamado. Por exemplo, suponha que você precise recuperar um objeto Person armazenado
Qual construtor o Hibernate deve chamar para recuperar um objeto Person? Você pode ver ?
2º E finalmente, usando reflexão, o Hibernate pode instanciar uma classe através de seu construtor sem arg. Então, quando você liga
O Hibernate irá instanciar seu objeto Person como segue
Que de acordo com a documentação da API
Moral da história
é similar a
Nada mais
fonte
name
eage
? Se não, ele usa outro construtor depois?Na verdade, você pode instanciar classes que não têm construtor 0-args; você pode obter uma lista dos construtores de uma classe, escolher um e invocá-lo com parâmetros falsos.
Embora isso seja possível, e eu acho que funcionaria e não seria problemático, você terá que concordar que é muito estranho.
Construir objetos da maneira que o Hibernate faz (eu acredito que ele invoca o construtor 0-arg e então provavelmente modifica os campos da instância diretamente via Reflection. Talvez ele saiba como chamar setters) vai um pouco contra como um objeto deve ser construído em Java- invoque o construtor com os parâmetros apropriados para que o novo objeto seja o objeto que você deseja. Eu acredito que instanciar um objeto e então transformá-lo é um pouco "anti-Java" (ou eu diria, anti-Java teórico puro) - e definitivamente, se você fizer isso por meio de manipulação direta de campo, haverá encapsulamento e todo aquele encapsulamento extravagante .
Eu acho que a maneira correta de fazer isso seria definir no mapeamento do Hibernate como um objeto deve ser instanciado a partir das informações na linha do banco de dados usando o construtor adequado ... mas isso seria mais complexo - o que significa que ambos os Hibernate seriam iguais mais complexo, o mapeamento ficaria mais complexo ... e tudo para ser mais "puro"; e não acho que isso teria uma vantagem sobre a abordagem atual (além de se sentir bem em fazer as coisas "da maneira certa").
Dito isso, e vendo que a abordagem do Hibernate não é muito "limpa", a obrigação de ter um construtor 0-arg não é estritamente necessária, mas posso entender um pouco o requisito, embora acredite que eles fizeram isso de maneira puramente "adequada "motivos, quando eles se desviaram do" caminho adequado "(embora por razões razoáveis) muito antes disso.
fonte
O Hibernate precisa criar instâncias como resultado de suas consultas (via reflexão), o Hibernate depende do construtor no-arg de entidades para isso, então você precisa fornecer um construtor no-arg. O que não está claro?
fonte
private
construtor está incorreto? Estou vendojava.lang.InstantiationException
até com umprivate
construtor para minha entidade JPA. referência .É muito mais fácil criar um objeto com um construtor sem parâmetros por meio de reflexão e, em seguida, preencher suas propriedades com dados por meio de reflexão, do que tentar combinar os dados com parâmetros arbitrários de um construtor parametrizado, com mudanças de nomes / conflitos de nomenclatura, lógica indefinida dentro do construtor, parâmetro define propriedades não correspondentes de um objeto, etc.
Muitos ORMs e serializadores exigem construtores sem parâmetros, porque os construtores paramterizados por meio de reflexão são muito frágeis e os construtores sem parâmetros fornecem estabilidade ao aplicativo e controle sobre o comportamento do objeto para o desenvolvedor.
fonte
O Hibernate usa proxies para carregamento lento. Se você não definir um construtor ou torná-lo privado, algumas coisas ainda podem funcionar - aquelas que não dependem do mecanismo de proxy. Por exemplo, carregar o objeto (sem construtor) diretamente usando a API de consulta.
Mas, se você usar o método session.load (), você enfrentará InstantiationException do proxy generator lib devido à indisponibilidade do construtor.
Esse cara relatou uma situação semelhante:
http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html
fonte
Confira esta seção das especificações da linguagem Java que explica a diferença entre classes internas estáticas e não estáticas: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
Uma classe interna estática não é conceitualmente diferente de uma classe geral regular declarada em um arquivo .java.
Uma vez que o Hibernate precisa instanciar o ProjectPK independentemente da instância do Project, o ProjectPK precisa ser uma classe interna estática ou declarado em seu próprio arquivo .java.
reference org.hibernate.InstantiationException: Nenhum construtor padrão
fonte