سؤال

لدي مشكلة مع السبات و leazyinitializationException. لقد بحثت وأجد الكثير من الإجابات ، لكن لا يمكنني استخدامها لحل مشكلتي ، لأنني يجب أن أقول ، أنا جديد على السبات.

أدير اختبارات Junit ، في حالة الخطأ هذا:

@Test
public void testAddPerson() {
    Set<Person> persons = service.getAllPersons();

    // create new person
    Person person = new Person();
    person.setEmail("john@doe.com");
    Project testProject = serviceProj.findProjectById(1);

    HashSet<Project> lister = new HashSet<Project>();
    lister.add(testProject);
    person.setProjects(lister);
    service.addPerson(person);

    testProject.getPersons().add(person);
    ...
}

آخر خط مبين:

testProject.getPersons().add(person);

يلقي هذا الخطأ:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.doe.john.domain.Project.persons, no session or session was closed

الشخص والمشروع ثنائي الاتجاه N: M:

شخص:

@ManyToMany(mappedBy="persons")
private Set<Project> projects = new HashSet<Project>();

Project.java:

@ManyToMany
@JoinTable(name = "Project_Person",
    joinColumns = {@JoinColumn(name="project_id", referencedColumnName="id")},
    inverseJoinColumns = {@JoinColumn(name="person_id", referencedColumnName="id")}
)
private Set<Person> persons = new HashSet<Person>();

إذا ما هي المشكلة؟

هل كانت مفيدة؟

المحلول

المشكلة هي أنه افتراضيًا يتم تحميل المجموعة بشكل كسول. هذا يعني أنه لن يتم تحميله بالفعل من قاعدة البيانات حتى يتم الوصول إليه. من أجل تحميله ، ستحتاج إلى جلسة/معاملة نشطة.

تتمثل الطريق السهل في تغييره إلى fethtype.eager الذي يتأكد من أن المجموعة يتم ملؤها على الفور.

--تحديث--

لقد واجهت نفس المشكلة مؤخرًا وانتهى بي الأمر بتعديل خدمتي الفعلية للتعامل مع هذا النوع من الأشياء. إعلان طريقة AddPerson في فئة Projectservice.

public void addPersonTo(Project project, Person person)
{
  project = em.merge(project); //EntityManager, not sure what you are using but you get the idea hopefully
  project.addPerson(person);
}

نصائح أخرى

ضع الكود الخاص بك داخل المعاملة - سيؤدي هذا إلى حل المشكلة لك

هل تجرب

person.getProjects().Add(testProject)

بدلاً من

HashSet<Project> lister = new HashSet<Project>();
lister.add(testProject);
person.setProjects(lister);

يجب أن تفعل ذلك منذ ذلك الحين ، وإلا فإنك ستفجر مجموعة إدارة سباتية.

من مرجع السبات:

بشكل افتراضي ، يستخدم Hibernate3 Lazy Select Fetching للمجموعات وجلب الوكيل الكسول للجمعيات ذات القيمة الواحدة. هذه الإعدادات الافتراضية منطقية بالنسبة لمعظم الجمعيات في غالبية التطبيقات.

إذا قمت بتعيين hibernate.default_batch_fetch_size ، فسيستخدم Hibernate تحسين دفع الدُفعة لجلب كسول. يمكن أيضًا تمكين هذا التحسين بمستوى أكثر حبيبًا.

يرجى العلم أن الوصول إلى جمعية كسول خارج سياق جلسة السبات المفتوحة سيؤدي إلى استثناء. فمثلا:

s = sessions.openSession();
Transaction tx = s.beginTransaction();

User u = (User) s.createQuery("from User u where u.name=:userName")
.setString("userName", userName).uniqueResult();
Map permissions = u.getPermissions();

tx.commit();
s.close();

Integer accessLevel = (Integer) permissions.get("accounts");  // Error!

نظرًا لعدم تهيئة مجموعة الأذونات عند إغلاق الجلسة ، لن تكون المجموعة قادرة على تحميل حالتها. لا يدعم السباتي التهيئة كسول للكائنات المنفصلة. يمكن إصلاح ذلك عن طريق تحريك الكود الذي يقرأ من المجموعة إلى قبل ارتكاب المعاملة مباشرة.

بدلاً من ذلك ، يمكنك استخدام مجموعة أو جمعية غير ملوثة ، من خلال تحديد Lazy = "false" لرسم خرائط الارتباط. ومع ذلك ، فإن المقصود استخدام التهيئة البطيئة لجميع المجموعات والجمعيات تقريبًا. إذا قمت بتحديد الكثير من الجمعيات غير البارزة في نموذج الكائن الخاص بك ، فسيقوم Hibernate بإحضار قاعدة البيانات بأكملها إلى الذاكرة في كل معاملة.

من ناحية أخرى ، يمكنك استخدام Joining Fetching ، وهو غير بسيط بطبيعته ، بدلاً من تحديد الجلب في معاملة معينة. سنشرح الآن كيفية تخصيص استراتيجية الجلب. في Hibernate3 ، فإن آليات اختيار استراتيجية الجلب متطابقة مع الجمعيات والمجموعات ذات القيمة الواحدة.

لذلك عليك إغلاق الجلسة بعد الوصول إلى المجموعة!

بدلاً من :

service.addPerson(person);

testProject.getPersons().add(person);

أعتقد أنه يجب أن يكون لديك:

testProject.getPersons().add(person);
service.addPerson(person);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top