다음과 같은 예외가 있습니다.
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)
main에서 다음 줄로 전화를 걸 때 :
Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());
getModelByModelGroup(int modelgroupid)
먼저 다음과 같이 방법을 구현했습니다 .
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;
}
}
예외가 있습니다. 그런 다음 친구는 항상 세션을 테스트 하고이 오류를 피하기 위해 현재 세션을 가져 오라고 제안했습니다. 그래서 나는 이것을했다 :
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;
}
}
}
그러나 여전히 같은 오류가 발생합니다. 이 오류에 대해 많은 것을 읽었으며 가능한 해결책을 찾았습니다. 그들 중 하나는 lazyLoad를 false로 설정하는 것이었지만 세션을 제어하도록 제안 된 이유는 이것을 허용하지 않습니다.
답변
여기서 잘못된 점은 트랜잭션을 커밋 할 때 세션 관리 구성이 세션을 닫도록 설정되어 있다는 것입니다. 다음과 같은 것이 있는지 확인하십시오.
<property name="current_session_context_class">thread</property>
구성에서.
이 문제를 극복하기 위해 세션 팩토리의 구성을 변경하거나 다른 세션을 열 수 있으며 게으른로드 된 오브젝트 만 요청할 수 있습니다. 그러나 여기서 제안하는 것은 getModelByModelGroup 자체 에서이 게으른 컬렉션을 초기화하고 호출하는 것입니다.
Hibernate.initialize(subProcessModel.getElement());
여전히 활성 세션에있을 때
그리고 마지막으로. 친절한 조언. 방법에 다음과 같은 것이 있습니다.
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
이 코드는 위의 몇 줄의 쿼리 문에서 id가 3 인 모델을 필터링합니다.
더 읽을 거리 :
답변
Spring을 사용하여 클래스를 @Transactional 로 표시하면 Spring이 세션 관리를 처리합니다.
@Transactional
public class MyClass {
...
}
를 사용 @Transactional
하면 트랜잭션 전파와 같은 많은 중요한 측면이 자동으로 처리됩니다. 이 경우 다른 트랜잭션 방법을 호출하면 “세션 없음”예외를 피하면서 진행중인 트랜잭션에 참여할 수 있습니다.
경고를 사용하는 경우 @Transactional
결과 동작에 유의하십시오. 일반적인 함정에 대해서는 이 기사 를 참조하십시오 . 예를 들어, 명시 적으로 전화하지 않아도 엔터티에 대한 업데이트가 유지 됩니다.save
답변
당신은 설정하려고 할 수 있습니다
<property name="hibernate.enable_lazy_load_no_trans">true</property>
hibernate.cfg.xml 또는 persistence.xml에서
답변
를 처리하는 가장 좋은 방법LazyInitializationException
은 JOIN FETCH
지시문 을 사용하는 것입니다 .
Query query = session.createQuery(
"from Model m " +
"join fetch m.modelType " +
"where modelGroup.id = :modelGroupId"
);
어쨌든, 일부 답변에서 제안한 다음 안티 패턴을 사용하지 마십시오.
때로는 DTO 돌기가 가져 오는 실체보다 더 나은 선택이 될 것입니다,이 방법은, 당신은 어떤을받지 않습니다 LazyInitializationException
.
답변
아래 주석에 대한 일대 다 관계에 대해 동일한 오류가 발생했습니다.
@OneToMany(mappedBy="department", cascade = CascadeType.ALL)
fetch = FetchType.EAGER를 추가 한 후 아래와 같이 변경되었습니다.
@OneToMany(mappedBy="department", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
답변
스프링 데이터 jpa, 스프링 부트를 사용하는 경우 application.properties에이 행을 추가 할 수 있습니다
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
답변
호출 할 때이 예외 session.getEntityById()
는 세션이 닫힙니다. 따라서 엔터티를 세션에 다시 연결해야합니다. 또는 쉬운 솔루션은 구성이다 default-lazy="false"
당신에 entity.hbm.xml
또는 주석을 사용하는 경우 만 추가 @Proxy(lazy=false)
엔터티 클래스.