Примечание: См. Мой собственный ответ на этот вопрос для примера того, как я решил эту проблему.Spring MVC + Hibernate: невозможно инициализировать прокси-сервер - нет Сессия
Я получаю следующее исключение в моей Spring MVC 4 + Hibernate 4 проекта:
org.hibernate.LazyInitializationException: не удалось инициализировать лениво коллекцию роли: com.mysite.Company.acknowledgements, не может инициализировать прокси - не сессии
После прочтения много других вопросов по поводу этого вопроса, я понимаю, почему это происходит исключение, но я не уверен, как это исправить в хорошем смысле. Я делаю следующее:
- My Spring MVC контроллер вызывает метод в службе
- Метод обслуживания вызывает метод в классе DAO
- метод в классе DAO выбирает объект сущности через Hibernate и возвращает его на службу вызова
- служба возвращает сгружен объект контроллера
- контроллер передает объект в виде (JSP)
- мнение пытается перебирать на многие-ко-многим Asso рирует, который лениво загружен (и, таким образом, прокси-объект)
- Исключение выбрасывается, так как сеанс закрыт в этой точке, и прокси-сервер не может загрузить связанные данные
я ранее работал с PHP и доктрины2, и этот способ делать вещи не вызывал проблем. Я пытаюсь выяснить, лучший способ решить эту проблему, потому что решения, которые я нашел до сих пор, кажется, не так велики:
- нагрузки ассоциация жадностью, потенциально погрузочные много ненужных данных
- Вызов
Hibernate.initialize(myObject.getAssociation());
- это означает, что мне нужно перебирать ассоциации, чтобы их инициализировать (я думаю), и только тот факт, что я должен это делать, вроде делает ленивую загрузку менее аккуратной. - Использование фильтра Spring, чтобы оставить сеанс открытым в взгляды, но я сомневаюсь, что это хорошо делать?
Я пытался использовать @Transactional
в своей службе, но без везения. Это имеет смысл, потому что я пытаюсь получить доступ к данным, которые еще не загружены после мой метод обслуживания возвращается. В идеале я хотел бы иметь доступ к любой ассоциации из моего представления. Я предполагаю, что недостатком инициализации ассоциаций в моей службе является то, что я должен явно определять, какие данные мне нужны, но это зависит от контекста (контроллера), в котором используется служба. Я не уверен, могу ли я сделать это в своем контроллере, не теряя абстракции, которую предоставляет уровень DBAL. Я надеюсь, что в этом есть смысл. В любом случае, было бы здорово, если бы мне не приходилось всегда явно определять, какие данные я хочу быть доступными для своего представления, но просто позвольте этому представлению делать что-то. Если это невозможно, я просто ищу наиболее элегантное решение проблемы.
Ниже приведен мой код.
Посмотреть
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h1><c:out value="${company.name}" /> (ID: <c:out value="${company.id}" />)</h1>
<c:forEach var="acknowledgement" items="${company.acknowledgements}">
<p><c:out value="${acknowledgement.name}" /></p>
</c:forEach>
Контроллер
@Controller
public class ProfileController {
@Autowired
private CompanyService companyService;
@RequestMapping("/profile/view/{id}")
public String view(Model model, @PathVariable int id) {
Company company = this.companyService.get(id);
model.addAttribute("company", company);
return "viewCompanyProfile";
}
}
Сервис
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDao companyDao;
@Override
public Company get(int id) {
return this.companyDao.get(id);
}
}
DAO
@Repository
@Transactional
public class CompanyDaoImpl implements CompanyDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public Company get(int id) {
return (Company) this.sessionFactory.getCurrentSession().get(Company.class, id);
}
}
предприятие компании
@Entity
@Table(name = "company")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
// Other fields here
@ManyToMany
@JoinTable(name = "company_acknowledgement", joinColumns = @JoinColumn(name = "company_id"), inverseJoinColumns = @JoinColumn(name = "acknowledgement_id"))
private Set<Acknowledgement> acknowledgements;
public Set<Acknowledgement> getAcknowledgements() {
return acknowledgements;
}
public void setAcknowledgements(Set<Acknowledgement> acknowledgements) {
this.acknowledgements = acknowledgements;
}
// Other getters and setters here
}
Квитирование объект
@Entity
public class Acknowledgement {
@Id
private int id;
// Other fields + getters and setters here
}
MVC-диспетчерская-servlet.xml (часть его)
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.mysite.company.entity</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven />
Заранее благодарен!
Благодарим вас за ответ. Я опробовал подход графа объектов, и для этого это приятное и чистое решение. Он решил проблему, и я напишу ответ с моим решением всем, кто заинтересован. Тем не менее, это похоже на то, что реализация графа сущностей [не является достаточно гибкой (пока)] (http://stackoverflow.com/questions/27360966/using-jpa-entity-graph-with-complex-conditions). Но это решило проблему! – Andy0708