কীভাবে org.hibernate.LazyInitializationException ঠিক করবেন - প্রক্সি শুরু করতে পারেনি - কোনও সেশন নেই


188

আমি নিম্নলিখিত ব্যতিক্রম পাই:

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)

যখন আমি নিম্নলিখিত লাইনগুলি থেকে কল করার চেষ্টা করি:

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;        
        }
    }
}

কিন্তু তবুও, একই ত্রুটি পান। আমি এই ত্রুটির জন্য অনেকগুলি পড়ছি এবং এর কিছু সম্ভাব্য সমাধান খুঁজে পেয়েছি। তাদের মধ্যে একটি আলস্যোডকে মিথ্যা হিসাবে সেট করা হয়েছিল তবে আমাকে এই কাজটি করার অনুমতি দেওয়া হচ্ছে না এজন্য আমাকে অধিবেশন নিয়ন্ত্রণ করার পরামর্শ দেওয়া হয়েছিল

উত্তর:


93

এখানে কী ভুল তা হ'ল আপনার লেনদেন করার সময় আপনার সেশন ম্যানেজমেন্ট কনফিগারেশনটি সেশন বন্ধ করার জন্য সেট করা আছে। আপনার মতো কিছু আছে কিনা তা পরীক্ষা করুন:

<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;
    }
}

এই কোডটি অন্তর্নিহিত দয়া করে কেবলমাত্র উপরের লাইনের দু'পক্ষের ক্যোয়ারী স্টেটমেন্টে 3 সমান আইডি সহ সেই মডেলগুলি ফিল্টার করুন।

আরও কিছু পড়া:

সেশন কারখানা কনফিগারেশন

বন্ধ অধিবেশন সমস্যা


1
ধন্যবাদ! আমি সংযোগগুলি আপনার দেওয়া আমাকে এই প্রস্তাব এক হিসাবে openSession (ব্যবহার করে আমার সমস্যা) getCurrentSession () এর পরিবর্তে মীমাংসিত, কিন্তু এখন আমি ভীত যদি এটি তা করার ভুল
Blerta Dhimitri

2
না এটা সম্ভবত ঠিক আছে। আপনার সেশন এবং লেনদেন পুরোপুরি নিয়ন্ত্রণ করতে সক্ষম হতে আরও কিছু পড়ুন। বেসিকগুলি জানা বাস্তবসম্মত গুরুত্বপূর্ণ কারণ সমস্ত উচ্চ স্তরের প্রযুক্তি যেমন স্প্রিং, হাইবারনেট এবং আরও অনেকগুলি একই ধারণাটিতে কাজ করে।
goroncy

179

যদি আপনি ক্লাসটিকে @ ট্রান্সজেকশনাল হিসাবে চিহ্নিত করেন তবে স্প্রিং সেশন পরিচালনা পরিচালনা করবে।

@Transactional
public class MyClass {
    ...
}

ব্যবহার করে @Transactional, লেনদেনের প্রচারের মতো অনেক গুরুত্বপূর্ণ দিক স্বয়ংক্রিয়ভাবে পরিচালিত হয়। এই ক্ষেত্রে যদি অন্য ট্রানজেকশনাল পদ্ধতিটিকে মেথড বলা হয় তবে "সেশন নয়" ব্যতিক্রম এড়ানো চলমান লেনদেনে যোগদানের বিকল্প থাকবে।

সতর্কতা আপনি যদি ব্যবহার করেন @Transactionalতবে দয়া করে ফলাফলের আচরণ সম্পর্কে সচেতন হন। সাধারণ সমস্যাগুলির জন্য এই নিবন্ধটি দেখুন । উদাহরণস্বরূপ, সুনির্দিষ্টভাবে কল না করলেও সত্তাগুলির আপডেটগুলি বহাল থাকেsave


21
আমি এই উত্তরের গুরুত্বকে বাড়াতে পারি না। আমি প্রথমে গুরুত্ব সহকারে এই বিকল্পটি চেষ্টা করার পরামর্শ দিই।
স্পার্কস্পাইডার

6
এছাড়াও লক্ষ করুন যে @EnableTransactionManagementলেনদেন সক্ষম করতে আপনাকে আপনার কনফিগারেশনে যুক্ত করতে হবে। " যদি অন্য একটি ট্রানজেকশনাল পদ্ধতি বলা হয় তবে পদ্ধতিটিতে চলমান লেনদেনে যোগদানের বিকল্প থাকবে " লেনদেনটি বিভিন্নভাবে প্রয়োগ করার জন্য, যেমন ইন্টারফেস প্রক্সি বনাম শ্রেণীর প্রক্সি বা অ্যাসপেক্টজে বুননগুলির জন্য এই আচরণটি আলাদা। পড়ুন ডকুমেন্টেশন
এরিক হাফার

1
আমরা কী বুঝতে পারি যে স্প্রিং Transactionalটীকাগুলি কেবলমাত্র লেনদেন পরিবর্তন করার জন্য নয়, কেবলমাত্র অ্যাক্সেসের জন্যও পরামর্শ দেওয়া হয়?
স্টিফেন

8
আমি পরীক্ষার জন্য ক্লাসের শীর্ষে এই টীকাকে গুরুত্বের সাথে ব্যবহার করার পরামর্শ দেব। বাস্তব কোড প্রতিটি পদ্ধতি পৃথক পৃথকভাবে লেনদেন হিসাবে চিহ্নিত করা উচিত। ক্লাসে সমস্ত পদ্ধতি না থাকলে ডাটাবেসের সাথে লেনদেনের সাথে খোলা সংযোগের প্রয়োজন হবে।
m1ld

1
কেবলমাত্র @ ট্রান্সজেকশনালের পরিবর্তে @ ট্রেডজেকশনাল (কেবলমাত্র পড়ুন = সত্য) রাখা কি নিরাপদ নয়?
হামেদজ

105

আপনি সেট করার চেষ্টা করতে পারেন

<property name="hibernate.enable_lazy_load_no_trans">true</property>

হাইবারনেট সিএফজি.এক্সএমএল বা দৃistence়তা.এক্সএমএল

এই সম্পত্তিটির সাথে মনে রাখার সমস্যাটি এখানে ভালভাবে ব্যাখ্যা করা হয়েছে


8
আপনি কি এর অর্থ ব্যাখ্যা করতে পারেন?
মোহিত কানওয়ার

2
আমি কি কৌতুহল করছি এটি কি করে। এটি আমার যে সমস্যাটি ছিল তা ঠিক করেছিল তবে আমি কেন তা বুঝতে চাই।
হাসান

3
অধ্যবসায়.এক্সএমএল এর জন্য:<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
এসিভি


6
এই সম্পত্তিটি ব্যবহার করবেন না, যদি স্প্রিং আপনার লেনদেনগুলি পরিচালনা করে তবে এই সম্পত্তিটি অনুবাদ এক্সপ্লোরেশনে অগ্রসর হবে, সিম্পলি স্প্রিং
আবেদনটি বন্ধ করে দেবে

54

LazyInitializationExceptionJOIN FETCHনির্দেশটি ব্যবহার করা হ্যান্ডেল করার সর্বোত্তম উপায় :

Query query = session.createQuery(
    "from Model m " +
    "join fetch m.modelType " +
    "where modelGroup.id = :modelGroupId"
);

যাইহোক, উত্তরগুলির কয়েকটি হিসাবে প্রস্তাবিত নীচের অ্যান্টি-প্যাটার্নগুলি ব্যবহার করবেন না:

কখনও কখনও, একটি ডিটিও প্রক্ষেপণ সত্তা আনার চেয়ে ভাল পছন্দ এবং এইভাবে, আপনি কোনও পাবেন না LazyInitializationException


কোন কলটিতে সমস্যা হচ্ছে তা আমি কীভাবে সনাক্ত করতে পারি? কলটি সনাক্ত করা আমার পক্ষে এতো কঠিন। অন্য কোন উপায় আছে ? পরীক্ষার উদ্দেশ্যে আমি ব্যবহার করেছি FetchType=EAGER, তবে এটি সঠিক সমাধান নয়, তাই না?
শান্তরাম টুপে

শুধু লগিং ব্যবহার করুন। এবং ইগ্রারটি খারাপ, হ্যাঁ।
ভ্লাদ মিহলসিয়া

তারপরে, আপনাকে @Transactionalপরিষেবাটি ছাড়ার আগে ডিটিও ব্যবহার করতে হবে বা সমস্ত সমিতি শুরু করা উচিত ।
ভ্লাদ মিহলসিয়া

2
আমাদের সেরা এন্টারপ্রাইজ অনুশীলনের পক্ষে পরামর্শ দেওয়া উচিত তবে তাড়াতাড়ি ঠিক করা উচিত নয়।
এটল্ডস

20

নীচের টীকায়নের জন্য আমি একের সাথে একাধিক সম্পর্কের ক্ষেত্রে একই ত্রুটি পাচ্ছিলাম।

@OneToMany(mappedBy="department", cascade = CascadeType.ALL)

ফেচ = ফেচটাইপ যুক্ত করার পরে নীচের হিসাবে পরিবর্তন করা হয়েছে Eএগ্রের, এটি আমার পক্ষে কাজ করেছে।

@OneToMany(mappedBy="department", cascade = CascadeType.ALL, fetch=FetchType.EAGER)

25
হ্যাঁ এটি এটি ঠিক করতে পারে তবে এখন আপনি পুরো ডেটা গাছটি লোড করছেন। এটি বেশিরভাগ ক্ষেত্রে নেতিবাচক পারফরম্যান্সের প্রভাব
ফেলবে

13

যদি আপনি স্প্রিং ডেটা জেপিএ ব্যবহার করেন, স্প্রিং বুট আপনি এই লাইনটি অ্যাপ্লিকেশন.প্রেটিটিতে যুক্ত করতে পারেন

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

7
এটি একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচিত হয়। vladmihalcea.com/…
সুদীপ ভান্ডারী

9

আপনি যখন ফোন করবেন তখন এই ব্যতিক্রম session.getEntityById(), অধিবেশনটি বন্ধ থাকবে। সুতরাং আপনাকে সেশনে সত্তাকে পুনরায় সংযুক্ত করতে হবে। বা সহজ সমাধানটি কেবল default-lazy="false" আপনার কাছে কনফিগার করা হয় entity.hbm.xmlবা আপনি যদি টিকা ব্যবহার করে থাকেন তবে @Proxy(lazy=false)কেবল আপনার সত্তা শ্রেণিতে যুক্ত করুন to


5

আমি একই সমস্যা সম্মুখীন। আমি মনে করি এটির সমাধানের আর একটি উপায় হ'ল আপনি মডেল থেকে আপনার এলিমেন্টটি আনতে যোগদানের জন্য কোয়েরিটি পরিবর্তন করতে পারেন:

Query query = session.createQuery("from Model m join fetch m.element where modelGroup.id = :modelGroupId")

4

এর অর্থ হ'ল আপনি যে অবজেক্টটিতে অ্যাক্সেস করার চেষ্টা করছেন সেটি লোড করা হয়নি, সুতরাং এমন একটি ক্যোয়ারী লিখুন যা আপনি অ্যাক্সেস করার চেষ্টা করছেন সেই অবজেক্টটির একটি জয়েন্ট আনবে

উদাহরণ:

আপনি যদি অবজেক্টএ থেকে অবজেক্টবি পাওয়ার চেষ্টা করছেন যেখানে অবজেক্টবি যেখানে অবজেক্টএর একটি বিদেশী কী।

প্রশ্ন :

SELECT objA FROM ObjectA obj JOIN FETCH obj.objectB objB

3

এখানে বেশ কয়েকটি ভাল উত্তর রয়েছে যা এই ত্রুটিটিকে একটি বিস্তৃত সুযোগে পরিচালনা করে। আমি স্প্রিং সিকিউরিটির সাথে একটি নির্দিষ্ট পরিস্থিতিতে ছুঁড়েছি যা দ্রুত ছিল, যদিও সম্ভবত অনুকূল নয়, ঠিক করুন।

ব্যবহারকারীর অনুমোদনের সময় (তাত্ক্ষণিকভাবে লগ ইন এবং প্রমাণীকরণ পাস করার পরে) আমি কাস্টম শ্রেণিতে একটি নির্দিষ্ট কর্তৃপক্ষের জন্য ব্যবহারকারীর সত্তা পরীক্ষা করছিলাম যা সিম্পলআরএলথ্যান্টিকেশনসুসেসহ্যান্ডলার প্রসারিত করে।

আমার ব্যবহারকারীর সত্তা ইউজারডিটেলগুলি প্রয়োগ করে এবং অলস বোঝা ভূমিকার একটি সেট রয়েছে যা "org.hibernate.LazyInitializationException - প্রক্সি শুরু করতে পারেনি - কোনও সেশন নয়" ব্যতিক্রম। সেটটি "ফেচ = ফেচটাইপ.এলজিওয়াই" থেকে "ফেচ = ফেচটাইপ.এগ্রার" এ পরিবর্তন করা আমার জন্য এটি স্থির করেছে।



2

বিভিন্ন ব্যবহারের ক্ষেত্রে একই ব্যতিক্রমের মুখোমুখি।

এখানে চিত্র বর্ণনা লিখুন

কেস ব্যবহার করুন: ডিটিও প্রজেকশন সহ ডিবি থেকে ডেটা পড়ার চেষ্টা করুন

সমাধান: ব্যবহার করুন পেতে পরিবর্তে পদ্ধতি লোড

জেনেরিক অপারেশন

public class HibernateTemplate {
public static Object loadObject(Class<?> cls, Serializable s) {
    Object o = null;
    Transaction tx = null;
    try {
        Session session = HibernateUtil.getSessionFactory().openSession();
        tx = session.beginTransaction();
        o = session.load(cls, s); /*change load to get*/
        tx.commit();
        session.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return o;
}

}

জেদী ক্লাস

public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private int customerId;

@Column(name = "Name")
private String customerName;

@Column(name = "City")
private String city;

//constructors , setters and getters

}

গ্রাহকদাও ইন্টারফেস

public interface CustomerDAO 
     {
   public CustomerTO getCustomerById(int cid);
     }

সত্তা স্থানান্তর অবজেক্ট শ্রেণি

public class CustomerTO {

private int customerId;

private String customerName;

private String city;

//constructors , setters and getters

}

কারখানার ক্লাস

public class DAOFactory {

static CustomerDAO customerDAO;
static {
    customerDAO = new HibernateCustomerDAO();
}

public static CustomerDAO getCustomerDAO() {
    return customerDAO;
}

}

সত্তা নির্দিষ্ট ডিএও

public class HibernateCustomerDAO implements CustomerDAO {

@Override
public CustomerTO getCustomerById(int cid) {
    Customer cust = (Customer) HibernateTemplate.loadObject(Customer.class, cid);
    CustomerTO cto = new CustomerTO(cust.getCustomerId(), cust.getCustomerName(), cust.getCity());
    return cto;
}

}

তথ্য পুনরুদ্ধার: পরীক্ষার ক্লাস

CustomerDAO cdao = DAOFactory.getCustomerDAO();
CustomerTO c1 = cdao.getCustomerById(2);
System.out.println("CustomerName -> " + c1.getCustomerName() + " ,CustomerCity -> " + c1.getCity());

উপস্থিত তথ্য

এখানে চিত্র বর্ণনা লিখুন

হাইবারনেট সিস্টেম দ্বারা উত্পন্ন উত্স এবং অনুসন্ধান

হাইবারনেট: গ্রাহক0_.এড1_0_0_, গ্রাহক0_. হিসাবে সিটি 2_0_0_, গ্রাহক0_. নাম হিসাবে গ্রাহকল্যাব 31 গ্রাহক0_ যেখানে গ্রাহক0_.আইডি =?

গ্রাহক নাম -> কোডি, গ্রাহকত্ব -> এলএ


1

আপনি যদি Grail'sফ্রেমওয়ার্ক ব্যবহার করছেন তবে অলস সূচনা ব্যতিক্রমটি ব্যবহার করে সমাধান করা সহজLazy করছেন তবে ডোমেন ক্লাসে নির্দিষ্ট ক্ষেত্রে কীওয়ার্ড ।

উদাহরণ স্বরূপ:

class Book {
    static belongsTo = [author: Author]
    static mapping = {
        author lazy: false
    }
}

এখানে আরও তথ্য সন্ধান করুন


1

আমার ক্ষেত্রে একটি ভুল জায়গা session.clear()থেকে এই সমস্যা দেখা দিচ্ছিল ।


1

এর অর্থ আপনি আপনার কোডে জেপিএ বা হাইবারনেট ব্যবহার করছেন এবং ব্যবসায়িক লজিক লেনদেন না করে ডিবিতে সংশোধনকারী অপারেশন করছেন। এর সহজ সমাধান হ'ল আপনার লেনদেনের কোডটি ট্রান্সএশনাল চিহ্নিত করুন



-2

আপনি আপনার * .hbm.xML ফাইলের মধ্যে অলস = মিথ্যা যোগ করেও এটি সমাধান করতে পারেন বা আপনি যখন ডিবি থেকে কোনও বস্তু পেয়ে যান তখন আপনি হাইবারনেট.ইনাইটে (অবজেক্ট) আপনার অবজেক্টটি শুরু করতে পারেন you


10
সাধারণত অলস = মিথ্যা যোগ করা ভাল ধারণা নয়। এজন্য
অলসটি

ওপি আগেই পরিষ্কার জানিয়েছিল যে তাকে এটি করতে দেওয়া হচ্ছে না।
জিঞ্জারহেড

-2

সার্লেট-কনটেক্সট.এক্সএমএলে নিম্নলিখিত পরিবর্তনগুলি করুন

    <beans:property name="hibernateProperties">
        <beans:props>

            <beans:prop key="hibernate.enable_lazy_load_no_trans">true</beans:prop>

        </beans:props>
    </beans:property>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.