У меня есть проект Java EE, а база данных MySQL управляется с помощью ORM.Я много работал с Hibernate, чтобы понять, что я делаю неправильно, и мне кажется, что я понимаю сессию / транзакцию, но я не знаю, как решить эту проблему в моем случае / архитектуре.
У меня есть проект иЧеловек, который находится в двунаправленном отношении n: m с таблицей соединений.Проект является владельцем карты.Теперь я хочу удалить человека, который подключен к проекту.
Итак, я подумал, я могу сделать это:
Person person = findPersonById(personId);
Set<Project> projects = person.getProjects();
Iterator<Project> iterator = projects.iterator();
while (iterator.hasNext()) {
Project project = iterator.next();
if (project.getPersons().contains(person)) {
project.getPersons().remove(person);
projectDao.updateProject(project);
}
}
personDao.removePerson(personId);
Но я получаю сообщение об ошибке в этой строке:
Iterator<Project> iterator = projects.iterator();
Но, похоже, это связано с:
Person person = findPersonById(personId);
и:
public Person findPersonById(int personId) {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session sess = sessionFactory.getCurrentSession();
Transaction tx = sess.beginTransaction();
try {
Person person = (Person)sess.createQuery("from Person where id = "+personId).list().get(0);
tx.commit();
return person;
}
catch (IndexOutOfBoundsException ex) {
return null;
}
}
Здесь я совершаю транзакцию и получаю только объект person, но не соответствующийпроекты.И итератор попытается их получить, но не сможет, потому что моя транзакция / сессия закрыта.Это из-за моей архитектуры:
У меня есть: IPersonService -> IPersonImplementation -> IPersonDao -> IPersonDaoImplementation , и только метод в IPersonDaoImplementation открывает и закрывает транзакцию.Поэтому в моей ServicePersonImplementation я не могу сделать несколько вещей, связанных с БД (я не хочу иметь FetchType.EAGER в моей аннотации @ManyToMany, потому что это приведет к загрузке большого количества ненужных вещей).Потому что, как только он возвращается из моей DaoImplementation, я не могу выполнять другие действия с возвращенным человеком (в моем случае получить все проекты, которые объединены с этим человеком).
Так что я могу сделать в моем случае?
С наилучшими пожеланиями Тим.
Обновление: PersonDaoImpl, метод удаления:
public void removePerson(int personId){
Person p = findPersonById(personId);
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session sess = sessionFactory.getCurrentSession();
Transaction tx = sess.beginTransaction();
sess.delete(p);
sess.flush();
tx.commit();
}
Трассировка ошибки:
ОШИБКА: org.hibernate.LazyInitializationException - не удалось лениво инициализировать коллекцию роли: com.testdomain.testproject.domain.Person.projects, ни один сеанс или сеанс не был закрыт org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекциюrole: com.testdomain.testproject.domain.Person.projects, ни один сеанс или сеанс не были закрыты в org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException (AbstractPersistentCollection.java:383) в org.hibernate.collection.AbstractPersistentControlTollectionTollectionTollectionTollection.ollectionTollection.ollectionTollection.ollectionTollection.ollectionJava: 375) в org.hibernate.collection.AbstractPersistentCollection.initialize (AbstractPersistentCollection.java:368) в org.hibernate.collection.AbstractPersistentCollection.read (AbstractPersistentCollection.java:111) в org.hibernate.collection.PersistentSetlection.PolistentSetlection.186) в com.testdomain.testproject.dao.impl.PersonDaoImplHibernate.removePerson (PersonDaoImplHibernate.java:71) в com.testdomain.testproject.service.impl.PersonServiceImpl.removePerson (PersonServiceImpl.jtestpromain.test для com.test)..service.PersonTest.testRemovePerson (PersonTest.java:180) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.jd.java: 25) в java.lang.reflect.Method.invoke (Method.java:597) в org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:44) в org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:15) в org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:41) в org.junit.internal.runners.statements.InvokeMethod.eavaate) ()по адресу org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored (BlockJUnit4ClassRunner.java:79) по адресу org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.javaitunjun) в org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:193) в org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:52)в org.junit.runners.ParentRunner.runChildren (ParentRunner.java:191)
в org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:42)
в org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:184)
в org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:28)
в org.junit.runners.ParentRunner.run (ParentRunner.java:236)
в org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java:46)
в org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution.java:38)
в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:467)
в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:683)
в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:390)
в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:197)
Не удалось удалить Person: не удалось лениво инициализировать коллекцию ролей: com.testdomain.testproject.domain.Person.projects, ни один сеанс или сеанс не был закрыт