注意:有关如何解决此问题的示例,请参阅我对这个问题的答案。
我的Spring MVC 4 + Hibernate 4项目中出现以下异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mysite.Company.acknowledgements, could not initialize proxy - no Session
在阅读了有关此问题的许多其他问题之后,我了解了为什么会发生此异常,但是我不确定如何以一种好的方式来解决它。我正在执行以下操作:
我以前使用过PHP和doctrine2,这种处理方式没有引起任何问题。我正在尝试找出解决此问题的最佳方法,因为到目前为止我发现的解决方案似乎并不那么出色:
Hibernate.initialize(myObject.getAssociation());
-这意味着我必须遍历关联以对其进行初始化(我想),而事实是我必须这样做,这使得延迟加载变得不太整齐我尝试在服务中使用
@Transactional
,但没有运气。这是有道理的,因为在我的服务方法返回后,我试图访问尚未加载的数据。理想情况下,我希望能够从我的观点访问任何关联。我猜想在服务中初始化关联的缺点是必须明确定义所需的数据,但这取决于使用服务的上下文( Controller )。我不确定是否可以在我的 Controller 中执行此操作而不丢失DBAL层提供的抽象。我希望这是有道理的。无论哪种方式,如果我不必总是显式定义我想对 View 可用的数据,那将是很棒的,而只需让 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
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-dispatcher-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 />
提前致谢!
最佳答案
最简单,最透明的解决方案是OSIV模式。如您所知,在此站点上和其他站点上都有关于此(反)模式以及替代方案的大量讨论,因此无需再次讨论。例如:
Why is Hibernate Open Session in View considered a bad practice?
但是,在我看来,并不是所有对OSIV的批评都是完全准确的(例如,在呈现 View 之前,事务将不会提交?是吗?如果您使用的是Spring实现,则为https://stackoverflow.com/a/10664815/1356423)
另外,请注意,JPA 2.1引入了“提取图”的概念,该概念使您可以更好地控制加载的内容。我还没有尝试过,但是也许这终于可以解决这个长期存在的问题了!
http://www.thoughts-on-java.org/2014/03/jpa-21-entity-graph-part-1-named-entity.html
关于spring - Spring MVC + Hibernate : could not initialize proxy - no Session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27299235/