gpt4 book ai didi

spring - Spring MVC + Hibernate : could not initialize proxy - no Session

转载 作者:行者123 更新时间:2023-12-04 13:26:57 24 4
gpt4 key购买 nike

注意:有关如何解决此问题的示例,请参阅我对这个问题的答案。

我的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



在阅读了有关此问题的许多其他问题之后,我了解了为什么会发生此异常,但是我不确定如何以一种好的方式来解决它。我正在执行以下操作:
  • 我的Spring MVC Controller 调用服务
  • 中的方法
  • 服务方法调用DAO类
  • 中的方法
  • DAO类中的方法通过Hibernate获取实体对象,并将其返回给调用服务
  • 服务将获取的对象返回给 Controller
  • Controller 将对象传递给 View (JSP)
  • 该 View 尝试对延迟加载(因此是代理对象)的多对多关联进行迭代
  • 引发异常,因为此时 session 已关闭,并且代理无法加载关联的数据

  • 我以前使用过PHP和doctrine2,这种处理方式没有引起任何问题。我正在尝试找出解决此问题的最佳方法,因为到目前为止我发现的解决方案似乎并不那么出色:
  • 紧急加载关联,可能会加载很多不必要的数据
  • 调用Hibernate.initialize(myObject.getAssociation());-这意味着我必须遍历关联以对其进行初始化(我想),而事实是我必须这样做,这使得延迟加载变得不太整齐
  • 使用Spring过滤器使 session 在 View 中保持打开状态,但是我怀疑这是一件好事吗?

  • 我尝试在服务中使用 @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/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com