BotProxy: Rotating Proxies Made for professionals. Really fast connection. Built-in IP rotation. Fresh IPs every day.
Note: See my own answer to this question for an example of how I solved this issue.
I am getting the following exception in my Spring MVC 4 + Hibernate 4 project:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mysite.Company.acknowledgements, could not initialize proxy - no Session
After reading a lot of other questions about this issue, I understand why this exception occurs, but I am not sure how to fix it in a good way. I am doing the following:
I have previously worked with PHP and doctrine2, and this way of doing things caused no problems. I am trying to figure out the best way to solve this, because the solutions that I found so far don't seem so great:
Hibernate.initialize(myObject.getAssociation());
- this means that I have to loop through associations to initialize them (I guess), and just the fact that I have to do this, kind of makes the lazy loading less neatI tried to use @Transactional
in my service, but without luck. This makes sense because I am trying to access data that has not yet been loaded after my service method returns. Ideally I would like to be able to access any association from within my view. I guess the drawback of initializing the associations within my service is that I have to explicitly define which data I need - but this depends on the context (controller) in which the service is used. I am not sure if I can do this within my controller instead without losing the abstraction that the DBAL layer provides. I hope that makes sense. Either way, it would be great if I didn't have to always explicitly define which data I want to be available to my view, but just let the view do its thing. If that is not possible, then I am just looking for the most elegant solution to the problem.
Below is my code.
View
<%@ 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
@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
@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);
}
}
Company entity
@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
}
Acknowledgement entity
@Entity
public class Acknowledgement {
@Id
private int id;
// Other fields + getters and setters here
}
mvc-dispatcher-servlet.xml (a part of it)
<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 />
Thanks in advance!
The simplest and most transparent solution is the OSIV pattern. As I'm sure you aware, there is plenty of discussion about this (anti)pattern and the alternatives both on this site and elsewhere so no need to go over that again. For example:
https://stackoverflow.com/questions/1103363/why-is-hibernate-open-session-in-view-considered-a-bad-practice
However, in my opinion, not all criticisms of OSIV are entirely accurate (e.g. the transaction will not commit till your view is rendered? Really? If you are using the Spring implementation then https://stackoverflow.com/a/10664815/1356423)
Also, be aware that JPA 2.1 introduced the concept of Fetch Graphs which give you more control over what is loaded. I haven't tried it yet but maybe this if finally a solution for this long standing problem!
http://www.thoughts-on-java.org/2014/03/jpa-21-entity-graph-part-1-named-entity.html