Eu recebo a seguinte exceção:
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at sei.persistence.wf.entities.Element_$$_jvstc68_47.getNote(Element_$$_jvstc68_47.java)
at JSON_to_XML.createBpmnRepresantation(JSON_to_XML.java:139)
at JSON_to_XML.main(JSON_to_XML.java:84)
quando tento ligar das principais linhas a seguir:
Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());
Eu implementei o getModelByModelGroup(int modelgroupid)
método primeiro assim:
public static Model getModelByModelGroup(int modelGroupId, boolean openTransaction) {
Session session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
Transaction tx = null;
if (openTransaction) {
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openTransaction) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new Exception("Non esiste ");
}
model = (Model)arrModels[0];
}
if (openTransaction) {
tx.commit();
}
return model;
} catch(Exception ex) {
if (openTransaction) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
e conseguiu a exceção. Em seguida, um amigo me sugeriu que sempre testasse a sessão e obtenha a sessão atual para evitar esse erro. Então eu fiz isso:
public static Model getModelByModelGroup(int modelGroupId) {
Session session = null;
boolean openSession = session == null;
Transaction tx = null;
if (openSession) {
session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openSession) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new RuntimeException("Non esiste");
}
model = (Model)arrModels[0];
if (openSession) {
tx.commit();
}
return model;
} catch(RuntimeException ex) {
if (openSession) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
}
mas ainda assim, obtenha o mesmo erro. Tenho lido muito sobre esse erro e encontrei algumas soluções possíveis. Uma delas era definir lazyLoad como false, mas não tenho permissão para fazer isso, por isso me sugeriram controlar a sessão
Se você usar o Spring, marcar a classe como @Transactional , o Spring tratará do gerenciamento de sessões.
Usando
@Transactional
, muitos aspectos importantes, como a propagação de transações, são tratados automaticamente. Nesse caso, se outro método transacional for chamado, o método terá a opção de ingressar na transação em andamento, evitando a exceção "no session".AVISO Se você usar
@Transactional
, esteja ciente do comportamento resultante. Consulte este artigo para obter armadilhas comuns. Por exemplo, as atualizações para entidades são mantidas, mesmo se você não chamar explicitamentesave
fonte
@EnableTransactionManagement
à sua configuração para permitir transações. " se outro método transacional for chamado, o método terá a opção de ingressar na transação em andamento " esse comportamento é diferente para as diferentes formas de implementação das transações, ou seja, proxy de interface versus proxy de classe ou tecelagem AspectJ. Consulte a documentação .Transactional
anotação do Spring é recomendada, não apenas para modificar transações, mas também para acessar apenas as transações?Você pode tentar definir
em hibernate.cfg.xml ou persistence.xml
O problema a ter em mente com esta propriedade está bem explicado aqui
fonte
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
hibernate.enable_lazy_load_no_trans
é um anti-padrões , certo?A melhor maneira de lidar com isso
LazyInitializationException
é usar aJOIN FETCH
diretiva:De qualquer forma, NÃO use os seguintes antipadrões, conforme sugerido por algumas das respostas:
hibernate.enable_lazy_load_no_trans
Às vezes, uma projeção de DTO é uma escolha melhor do que buscar entidades e, dessa forma, você não receberá nenhuma
LazyInitializationException
.fonte
FetchType=EAGER
, mas essa não é a solução correta, certo?@Transactional
serviço.Eu estava recebendo o mesmo erro de um para muitos relacionamentos na anotação abaixo.
Alterado como abaixo, após adicionar fetch = FetchType.EAGER, funcionou para mim.
fonte
se você usar o jpa de dados spring, boot inicial, poderá adicionar esta linha em application.properties
fonte
Esta exceção, devido a quando você ligar
session.getEntityById()
, a sessão será fechada. Portanto, você precisa anexar novamente a entidade à sessão. A solução Or Easy é apenas configurardefault-lazy="false"
para o seuentity.hbm.xml
ou, se você estiver usando anotações, adicionar@Proxy(lazy=false)
à sua classe de entidade.fonte
Eu encontrei o mesmo problema. Acho que outra maneira de corrigir isso é que você pode alterar a consulta para ingressar buscar seu elemento do modelo da seguinte maneira:
fonte
Isso significa que o objeto que você está tentando acessar não está carregado, portanto, escreva uma consulta que faça uma busca por junção do objeto que você está tentando acessar.
Por exemplo:
Se você estiver tentando obter o ObjectB do ObjectA, em que o ObjectB é uma chave estrangeira no ObjectA.
Inquerir :
fonte
Existem várias boas respostas aqui que tratam desse erro em um escopo amplo. Encontrei uma situação específica com o Spring Security que tinha uma solução rápida, embora provavelmente não ótima.
Durante a autorização do usuário (imediatamente após o login e a autenticação), eu estava testando uma entidade do usuário para uma autoridade específica em uma classe personalizada que estende o SimpleUrlAuthenticationSuccessHandler.
Minha entidade de usuário implementa UserDetails e possui um conjunto de funções carregadas preguiçosamente que lançou a exceção "org.hibernate.LazyInitializationException - não pôde inicializar o proxy - sem sessão". Alterar esse conjunto de "fetch = FetchType.LAZY" para "fetch = FetchType.EAGER" corrigiu isso para mim.
fonte
Se você estiver usando JPQL, use JOIN FETCH é a maneira mais fácil: http://www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_
fonte
Enfrentou a mesma exceção em diferentes casos de uso.
Caso de uso: tente ler dados do banco de dados com projeção DTO.
Solução: use o método get em vez de carregar .
Operação genérica
}
Classe de persistência
Interface CustomerDAO
Classe de Objeto de Transferência de Entidade
}
Classe de fábrica
}
DAO específico da entidade
}
Recuperando Dados: Classe de Teste
Dados atuais
Consulta e Saída Gerada pelo Sistema Hibernate
Hibernação: selecione customer0_.Id como Id1_0_0_, customer0_.City como cidade2_0_0_, customer0_.Name como Name3_0_0_ do CustomerLab31 customer0_ onde customer0_.Id =?
CustomerName -> Cody, CustomerCity -> LA
fonte
Se você estiver usando o
Grail's
Framework, é simples resolver uma exceção de inicialização lenta usando aLazy
palavra-chave em um campo específico na Classe de Domínio.Por exemplo:
Encontre mais informações aqui
fonte
No meu caso, um extraviado
session.clear()
estava causando esse problema.fonte
Isso significa que você está usando JPA ou hibernar em seu código e executando operações de modificação no DB sem fazer a transação da lógica de negócios. A solução mais simples para isso é marcar seu código @Transactional
fonte
usa session.get (*. class, id); mas não carrega função
fonte
você também pode resolvê-lo adicionando lazy = false ao seu arquivo * .hbm.xml ou pode iniciar seu objeto no Hibernate.init (Object) ao obter o objeto do db
fonte
Faça as seguintes alterações no servlet-context.xml
fonte