1. ホーム

[解決済み] org.hibernate.LazyInitializationException - プロキシを初期化できませんでした - セッションがありませんを修正する方法

2022-04-03 09:58:54

質問

以下のような例外が発生します。

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 に等しいモデルをフィルタリングしてください。

もう少し読みます。

セッションファクトリの設定

閉じたセッションの問題