懒惰地在Hibernate中初始化一个集合

时间:2017-02-27 09:32:25

标签: java hibernate

在我的托管bean中,我有一个代码如下:

throwError

但是当我运行它时,我收到此错误消息:

FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> map = context.getExternalContext().getRequestParameterMap();
int pageIndex = Integer.valueOf(map.get("page"));
int pageItem = Integer.valueOf(map.get("pageItem"));
int widget = Integer.valueOf(map.get("widget"));

DashboardPageItem dashboardPageItem = new DashboardPageItem();

dashboardPageItem.setPosition(pageItem);
dashboardPageItem.setWidget(widgetService.trouver(widget));

for (DashboardPage dp : dashboard.getPages()) {
    if (dp.getIndex() == pageIndex) {
        dashboardPageItem.setDashboardPage(dp);
        dp.getDashboardPageItems().add(dashboardPageItem);
    }
}

所以,我有一个名为org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.dashboard.entity.DashboardPage.dashboardPageItems, no session or session was closed 的班级,此班级列表中包含Dashboard,每个DashboardPage都有一个DashboardPage列表。

(请注意,我总是想在获取DashboardPage条目时获取所有DashboardPageItem列表,而对于DashboardPage列表,每当我调用Dashboard条目时,我都不需要获取列表,仅在某些情况下。)

我在没有JPA的情况下使用Hibernate,这是上述每个类的hbm:

控制板:

DashboardPageItem

DashboardPage:

<class name="Dashboard" table="t_dashboard_das">
    <id name="id" column="das_id">
        <generator class="native"/>
    </id>
    <property name="name" column="das_name"/>
    <property name="description" column="das_description"/>
    <property name="visibility" column="das_visibility"/>

    <many-to-one name="createur" 
                 column="fk_sal_id"
                 foreign-key="sal_id"
                 not-null="false"
                 lazy="proxy"/>

    <many-to-one name="role" 
                 column="fk_rol_id"
                 foreign-key="rol_id"
                 not-null="false"
                 lazy="proxy"/>

    <bag table="t_dashboard_page_dpa" name="pages" inverse="true" lazy="true" cascade="all">
        <key column="fk_das_id" not-null="true" unique="false" foreign-key="das_id"/>
        <one-to-many class="com.dashboard.entity.DashboardPage"></one-to-many>    
    </bag>
</class>

DashboardPageItem:

<class name="DashboardPage" table="t_dashboard_page_dpa">
    <id name="id" column="dpa_id">
        <generator class="native"/>
    </id> 

    <property name="name" column="dpa_name"/>
    <property name="index" column="dpa_index"/>
    <property name="model" column="dpa_model"/>

    <many-to-one name="dashboard" 
                 column="fk_das_id"
                 foreign-key="das_id"
                 not-null="false"
                 lazy="proxy"/>

    <bag table="t_dashboard_page_item_dpi" name="dashboardPageItems" inverse="true" lazy="true" cascade="all">
        <key column="fk_dpa_id" not-null="true" unique="false" foreign-key="dpa_id"/>
        <one-to-many class="com.dashboard.entity.DashboardPageItem"></one-to-many>    
    </bag>             
</class>

我该如何解决这个问题?

编辑:

这是我检索<class name="DashboardPageItem" table="t_dashboard_page_item_dpi"> <id name="id" column="dpi_id"> <generator class="native"/> </id> <property name="position" column="dpi_position"/> <many-to-one name="dashboardPage" column="fk_dpa_id" foreign-key="dpa_id" not-null="false" lazy="proxy"/> <many-to-one name="widget" column="fk_wid_id" foreign-key="wid_id" not-null="false" lazy="proxy"/> </class> 的方式:

Dashboard

这将致电:

this.dashboard = dashboardService.trouver(idDashboard);

其中 public K get(int id) { if(id == 0) return null; return (K) getSessionFactory().getCurrentSession().get(getClasse(),id); } K

4 个答案:

答案 0 :(得分:0)

理想情况下,您不希望将hibernate代理发送到您的JSF托管bean(将它们打包到DTO中并继续处理)。

但是关于你目前的情况,我建议创建一个新的服务方法来更新仪表板(首先它将合并仪表板以使其由持久性提供者管理):

@Transactional
public void updateDashboard(Dashboard dashboard, DashboardPageItem dashboardPageItem){
      Dashboard managedDashboard = session.merge(dashboard);
       for (DashboardPage dp : managedDashboard .getPages()) {
         DashboardPage managedDp = session.merge(dp);
        if (managedDp.getIndex() == pageIndex) {
            dashboardPageItem.setDashboardPage(managedDp);
            managedDp.getDashboardPageItems().add(dashboardPageItem);
        }
       }

       session.merge(managedDashboard);
 }

然后从您管理的bean中调用:

dashboardService.updateDashboard(dashboard, dashobardPageItem)

多亏了你,你会在事务上下文中处理你的实体(我建议在大多数情况下这样做)。

答案 1 :(得分:0)

所以这里的问题是你想在事务之外访问一个惰性集合。

有多种方法可以解决此问题。

  1. 在交易中访问延迟收藏
  2. 在查询中直接获取延迟收藏
  3. 使用第一种方法,您将解决问题,但可能存在性能问题。

    首选方式是第二种方式。

    您可以在此处详细了解: http://blog.arnoldgalovics.com/2017/02/27/lazyinitializationexception-demystified/

    我真的建议阅读整篇文章,因为它会澄清你头脑中的很多东西。

答案 2 :(得分:-1)

在您的信息中心实体中,请设为lazy = false。默认情况下,lazy被hibernate标记为true。

答案 3 :(得分:-1)

我认为这是因为您不在交易环境中。如果你使用spring或cdi,也许你应该在你的课上添加@Transactional。或@Stateless如果您使用的是ejb